在ASP.NET开发中,经常需要在复杂的控件层次结构中查找特定的控件,例如Repeater等。通常情况下,只能使用标准的FindControl方法,但这个方法只能在同一NamingContainer内查找具有给定ID的控件。为了解决这个问题,编写了一些扩展方法,希望能够帮助大家更好地处理这些情况。
有时候需要获取父控件下所有特定类型的子控件,例如获取所有的TextBox控件。以下是一个扩展方法的示例:
public static IEnumerable<T> GetAllChildControlsOfType<T>(this Control parent) where T : Control
{
if (parent == null)
throw new ArgumentNullException("parent");
foreach (Control c in parent.Controls)
{
if (typeof(T).IsInstanceOfType(c))
yield return (T)c;
foreach (T tc in c.GetAllChildControlsOfType<T>())
yield return tc;
}
yield break;
}
这个方法递归地遍历父控件的所有子控件,如果子控件是指定类型的实例,则将其返回。
有时候并不关心控件的具体类型,只关心它是否实现了某个接口,例如IButtonControl。以下是一个扩展方法的示例:
public static IEnumerable<T> GetAllChildControlsWithInterface<T>(this Control parent)
{
if (!typeof(T).IsInterface)
throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, "Type '{0}' is not an interface", typeof(T).ToString()));
if (parent == null)
throw new ArgumentNullException("parent");
foreach (object c in parent.Controls)
{
if (typeof(T).IsInstanceOfType(c))
yield return (T)c;
Control ctrl = c as Control;
if (ctrl != null)
foreach (T tc in ctrl.GetAllChildControlsWithInterface<T>())
yield return tc;
}
yield break;
}
这个方法递归地遍历父控件的所有子控件,如果子控件实现了指定的接口,则将其返回。
有时候需要根据ID查找控件,例如在Repeater中查找所有ID为"FirstName"的TextBox控件。以下是一个扩展方法的示例:
public static IEnumerable<T> FindAllControl<T>(this Control parent, string id) where T : Control
{
if (string.IsNullOrEmpty(id))
throw new ArgumentNullException("id");
return parent.GetAllChildControlsOfType<T>().Where(c => string.Equals(c.ID, id, StringComparison.OrdinalIgnoreCase));
}
这个方法首先获取所有指定类型的子控件,然后筛选出ID与给定ID相等的控件。
有时候只需要找到第一个具有给定ID的控件,而不需要找到所有这样的控件。以下是一个扩展方法的示例:
public static T FindControl<T>(this Control parent, string id) where T : Control
{
return parent.FindAllControl<T>(id).FirstOrDefault();
}