在ASP.NET中,我可以将一堆下拉列表转换为一系列下拉菜单吗?

时间:2011-03-11 11:08:42

标签: asp.net drop-down-menu

我的asp页面中有45个下拉列表。我可以将一些方法应用于所有这些下拉菜单。为了便于使用,是否可以将它们转换为一系列下拉列表?

2 个答案:

答案 0 :(得分:2)

我会使用递归来查找页面上的所有下拉列表。基于此post,它将类似于:

    public static List<T> FindControls<T>(System.Web.UI.ControlCollection Controls) where T : class
{
List<T> found = new List<T>();
FindControls<T>(Controls, found);
return found;
}
    private static void FindControls<T>(System.Web.UI.ControlCollection Controls, List<T> found) where T : class
    {
         if (Controls != null && Controls.Count > 0)
         {
              for (int i = 0; i < Controls.Count; i++)
              {
                   if (Controls[i] is T)
                   {
                        found.add(Controls[i] as T);
                   }
                   else
                        FindControl<T>(Controls[i].Controls, found);
              }
         }

       }

获得下拉列表后,您可以应用您认为合适的任何方法。

答案 1 :(得分:1)

使用Linq to Objects,Extension方法和泛型,我们可以非常简洁:

获取所有DropDowns的方法调用

var DropDowns = FindAllControlsByType<DropDownList>(MyBaseControlArray);

查找控制方法

public static IEnumerable<Control> FindAllControlsByType<T>(IEnumerable<Control> MyCollection) where T : class
{
    return MyCollection.Cast<Control>().Descendants(d => d.Controls.Cast<Control>()).Where(l => l.GetType().Equals(typeof(T)));
}

后代扩展方法

static public class LinqExtensions
{
    static public IEnumerable<T> Descendants<T>(this IEnumerable<T> source, 
                                                Func<T, IEnumerable<T>> DescendBy)
    {
        foreach (T value in source)
        {
            yield return value;

            foreach (T child in DescendBy(value).Descendants<T>(DescendBy))
            {
                yield return child;
            }
        }
    }
}

修改

我一直在考虑使这一切都更通用,所以这里是一个完全通用的解决方案,它将从指定的起点遍历一个对象图,提取给定类型的所有元素。

public static class Utils
{
    public static IEnumerable<IEnumerable<T>> GetCollections<T>(object obj)
    {
        if (obj == null) throw new ArgumentNullException("obj");
        var type = obj.GetType();
        var res = new List<IEnumerable<T>>();
        foreach (var prop in type.GetProperties())
        {
            // is IEnumerable<T>?
            if (typeof(IEnumerable<T>).IsAssignableFrom(prop.PropertyType))
            {
                var get = prop.GetGetMethod();
                if (!get.IsStatic && get.GetParameters().Length == 0) // skip indexed & static
                {
                    var collection = (IEnumerable<T>)get.Invoke(obj, null);
                    if (collection != null) res.Add(collection);
                }
            }
        }
        return res;
    }

    public static IEnumerable<V> FindAllControlsByType<V, T>(V MyCollection) where T : class
    {
        return Utils.GetCollections<V>(MyCollection).Descendants(d => d).Where(l => typeof(T).IsAssignableFrom(l.GetType()));
    }
}

static public class LinqExtensions
{
    static public IEnumerable<T> Descendants<T>(this IEnumerable<IEnumerable<T>> source,
                                                Func<IEnumerable<IEnumerable<T>>, IEnumerable<IEnumerable<T>>> DescendBy)
    {
        foreach (IEnumerable<T> collection in source)
        {
            foreach (T value in collection)
            {
                yield return value;

                foreach (T child in DescendBy(Utils.GetCollections<T>(value)).Descendants<T>(DescendBy))
                {
                    yield return child;
                }
            }
        }
    }
}

我们可以使用:

来调用它
var DropDowns = Utils.FindAllControlsByType<Control, DropDownList>(BaseControl);

基本上,这两种类型是基类和要提取的特定子类。您将注意到该进程标识了基类的每个实例中包含的基类的所有集合。这意味着我们不会将Controls作为集合绑定,并且可以在其他结构中使用它。欢迎任何额外的优化。