我一直在思考如何在一个页面上获取所有控件,然后在相关问题中对它们执行任务:
How to Search Through a C# DropDownList Programmatically个
我需要的代码,可以扫描页面,获得所有DropDownList控件,并返回到一个列表中.
我目前必须编辑每个单独的控件,我宁愿能够动态循环每个控件来完成我的任务.
我一直在思考如何在一个页面上获取所有控件,然后在相关问题中对它们执行任务:
How to Search Through a C# DropDownList Programmatically个
我需要的代码,可以扫描页面,获得所有DropDownList控件,并返回到一个列表中.
我目前必须编辑每个单独的控件,我宁愿能够动态循环每个控件来完成我的任务.
基本上,我们的 idea 是使用以下命令包装遍历Controls集合的递归:
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);
}
}
使用它:
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]:这里有一个更优雅的方式来实现这个目标.我编写了两个扩展方法,可以在两个方向上遍历控制树.这些方法以更Linq的方式编写,因为它会生成一个可枚举的:
/// <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;
}
}
}
}
}
由于this
关键字,这些方法是扩展方法,可以简化代码.
例如,要查找页面中的全部DropDownList
个,只需调用:
var allDropDowns = this.Page.FindControl<DropDownList>();
由于使用了yield
关键字,而且Linq足够聪明,可以推迟枚举的执行,因此可以调用(例如):
var allDropDowns = this.Page.FindDescendants<DropDownList>();
var firstDropDownWithCustomClass = allDropDowns.First(
ddl=>ddl.CssClass == "customclass"
);
一旦First
方法中的谓词得到满足,枚举就会停止.整个控制树都无法行走.