开发者

In ASP.NET, can I convert a bunch of dropdowns into an array of dropdowns?

I have 45 dropdown lists in my asp page. There are some 开发者_如何学Gomethods that I can apply to all of these dropdowns. Is it possible to convert them into an array of dropdowns for ease of use?


I would use recursion to look for all dropdowns on your page. Based on this post it would be something like:

    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);
              }
         }

       }

Once you have your list of dropdowns you can apply whatever methods you see fit.


Using Linq to Objects, an Extension method and Generics we can make this very concise thus:

Method Call to Get all DropDowns

var DropDowns = FindAllControlsByType<DropDownList>(MyBaseControlArray);

Find Controls Method

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)));
}

Descendants Extension Method

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;
            }
        }
    }
}

EDIT

I've been looking at making this all a mite more generic so here is a completely generic solution that will traverse an object graph from a specified start point extracting all elements of the given type.

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;
                }
            }
        }
    }
}

And we can call that using:

var DropDowns = Utils.FindAllControlsByType<Control, DropDownList>(BaseControl);

Basically the two types are the base class and the specific child class that you want to extract. You'll notice that the process identifies all collections of the base class that are contained within each instance of the base class. This means we're not tied to Controls as the collection and could use this within other structures. Any additional optimisations welcomed.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜