I have been pondering how I can get all controls on a page and then perform a task on them in this related question:
开发者_JAVA技巧How to Search Through a C# DropDownList Programmatically
I need code that can scan the page, get all DropDownList Controls and return them in a list.
I'm currently having to edit each individual control, I would rather be able to dynamically loop over each control to preform my task.
Check my previous SO answer.
Basically, the idea is to wrap the recursion of iterating through the controls collection using :
private void GetControlList<T>(ControlCollection controlCollection, List<T> resultCollection)
where T : Control
{
foreach (Control control in controlCollection)
{
//if (control.GetType() == typeof(T))
if (control is T) // This is cleaner
resultCollection.Add((T)control);
if (control.HasControls())
GetControlList(control.Controls, resultCollection);
}
}
and to use it :
List<DropDownList> allControls = new List<DropDownList>();
GetControlList<DropDownList>(Page.Controls, allControls )
foreach (var childControl in allControls )
{
// call for all controls of the page
}
[Edited 11/26/2013]: here is a more elegant way to reach this goal. I wrote two extensions methods that can walk the control tree in both directions. The methods are written in a more Linq way as it produces an enumerable:
/// <summary>
/// Provide utilities methods related to <see cref="Control"/> objects
/// </summary>
public static class ControlUtilities
{
/// <summary>
/// Find the first ancestor of the selected control in the control tree
/// </summary>
/// <typeparam name="TControl">Type of the ancestor to look for</typeparam>
/// <param name="control">The control to look for its ancestors</param>
/// <returns>The first ancestor of the specified type, or null if no ancestor is found.</returns>
public static TControl FindAncestor<TControl>(this Control control) where TControl : Control
{
if (control == null) throw new ArgumentNullException("control");
Control parent = control;
do
{
parent = parent.Parent;
var candidate = parent as TControl;
if (candidate != null)
{
return candidate;
}
} while (parent != null);
return null;
}
/// <summary>
/// Finds all descendants of a certain type of the specified control.
/// </summary>
/// <typeparam name="TControl">The type of descendant controls to look for.</typeparam>
/// <param name="parent">The parent control where to look into.</param>
/// <returns>All corresponding descendants</returns>
public static IEnumerable<TControl> FindDescendants<TControl>(this Control parent) where TControl : Control
{
if (parent == null) throw new ArgumentNullException("control");
if (parent.HasControls())
{
foreach (Control childControl in parent.Controls)
{
var candidate = childControl as TControl;
if (candidate != null) yield return candidate;
foreach (var nextLevel in FindDescendants<TControl>(childControl))
{
yield return nextLevel;
}
}
}
}
}
Thanks to the this
keyword, these methods are extensions methods and can simplify the code.
For example, to find all DropDownList
in the page, you can simply call:
var allDropDowns = this.Page.FindControl<DropDownList>();
Because of the use of the yield
keyword, and because Linq is smart enough to defer execution of the enumeration, you can call (for example):
var allDropDowns = this.Page.FindDescendants<DropDownList>();
var firstDropDownWithCustomClass = allDropDowns.First(
ddl=>ddl.CssClass == "customclass"
);
The enumeration will stop as soon as the predicate in the First
method is satisfied. The whole control tree won't be walked.
foreach (DropDownList dr in this.Page.Form.Controls.OfType<DropDownList>())
{
}
Here is a recursive version that returns a control collection of the requested type instead of utilizing another argument:
using System.Collections.Generic;
using System.Web.UI;
// ...
public static List<T> GetControls<T>(ControlCollection Controls)
where T : Control {
List<T> results = new List<T>();
foreach (Control c in Controls) {
if (c is T) results.Add((T)c);
if (c.HasControls()) results.AddRange(GetControls<T>(c.Controls));
}
return results;
}
Insert into your class (static optional).
Had this very question and while I found Steve B's answer useful, I wanted an extension method, so re-factored it:
public static IEnumerable<T> GetControlList<T>(this ControlCollection controlCollection) where T : Control
{
foreach (Control control in controlCollection)
{
if (control is T)
{
yield return (T)control;
}
if (control.HasControls())
{
foreach (T childControl in control.Controls.GetControlList<T>())
{
yield return childControl;
}
}
}
}
Looping through controls on a page isn't hard - you just have to look within each control for more controls.
You could do something like
foreach(var control in Page)
{
if(control is DropDownList)
{
//Do whatever
}
else
{
//Call this function again to search for controls within this control
}
}
You can use recursive logic to get all of the controls, like this:
private void PopulateSelectList(Control parentCtrl, List<DropDownList> selectList)
{
foreach (Control ctrl in parentCtrl.Controls)
{
if (ctrl is DropDownList)
{
selectList.Add(((DropDownList)ctrl);
continue;
}
FindAllControls(ctrl, selectList);
}
}
var dropDownLists = new List<DropDownList>();
foreach (var control in this.Controls)
{
if (control is DropDownList)
{
dropDownLists.Add( (DropDownList)control );
}
}
This works if you use the form components from system.web.ui however this does not work when you use them from system.web.mvc apparently so i came up with the following work around.
for (Int32 idx = 0; idx < formCollection.Count; idx += 1)
{
String Name = formCollection.Keys[idx];
String value = formCollection[idx];
if (Name.Substring(0, 3).ToLower() == "chk")
{
Response.Write(Name + " is a checkbox <br/>");
}
else if (Name.Substring(0, 5).ToLower() == "txtar")
{
Response.Write(Name + " is a text area <br/>");
}
else if (Name.Substring(0, 2).ToLower() == "rd")
{
Response.Write(Name + " is a RadioButton <br/>");
}
}
This works for me however i found out that radio button if not selected is null so doesnt return anything which is ok i dont have to write anything to the database if it is null
精彩评论