【问题标题】:How to merge multiple ControlCollections in C#?如何在 C# 中合并多个 ControlCollection?
【发布时间】:2009-11-12 19:22:38
【问题描述】:

有没有一种优雅的方式来做到这一点?也许与 Linq 一起使用?

对于这样的事情:

List<ControlCollection> list = { ... }

List<Control> merged = list.MergeAll();

编辑:从某种意义上说,最终集合将是一维的,所有控件都将存在,而不是嵌套。

【问题讨论】:

    标签: c# .net linq collections


    【解决方案1】:

    这个怎么样:

    public static void Append(this System.Windows.Forms.Control.ControlCollection collection, System.Windows.Forms.Control.ControlCollection newCollection)
    {
        Control[] newControl = new Control[newCollection.Count];
        newCollection.CopyTo(newControl, 0);
        collection.AddRange(newControl);
    }
    

    用法:

        Form form1 = new Form();
        Form form2 = new Form();
        form1.Controls.Append(form2.Controls);
    

    这将使控制树变平:

    public static void FlattenAndAppend(this System.Windows.Forms.Control.ControlCollection collection, System.Windows.Forms.Control.ControlCollection newCollection)
    {
        List<Control> controlList = new List<Control>();
        FlattenControlTree(collection, controlList);
    
        newCollection.AddRange(controlList.ToArray());
    }
    
    public static void FlattenControlTree(System.Windows.Forms.Control.ControlCollection collection, List<Control> controlList)
    {
        foreach (Control control in collection)
        {
            controlList.Add(control);
            FlattenControlTree(control.Controls, controlList);
        }
    }
    

    【讨论】:

    • 谢谢,我实际上忘记了一些事情。它是否处理控件中的控件,从而摆脱所有嵌套级别?
    • 是的。当控件移动时,它的所有子控件也会移动。
    • 不,我的意思是,它是否添加了它们,所以列表不是多维的。
    • 你为什么使用 Array.CreateInstance ?写new Control[newCollection.Count]不是更容易吗?
    • 感谢我的代码也做了类似的事情,所以我想这是唯一的方法。
    【解决方案2】:

    Linq 有 ConcatUnion 方法。是您正在寻找的其中之一吗?

    【讨论】:

    • 谢谢关闭,但他们仍然需要我为每个元素对它们进行循环。我希望通过一个电话或其他方式来做到这一点。
    • 为什么需要循环?您只需在结果上使用ToList() 即可获得List&lt;Control&gt;
    【解决方案3】:

    树扩展方法

    static class TreeExtensions
    {
      public static IEnumerable<R>TraverseDepthFirst<T, R>(
          this T t,
          Func<T, R> valueselect,
          Func<T, IEnumerable<T>> childselect)
      {
        yield return valueselect(t);
    
        foreach (var i in childselect(t))
        {
          foreach (var item in i.TraverseDepthFirst(valueselect, childselect))
          {
            yield return item;
          }
        }
      }
    }
    

    用法:

    Control c = root_form_or_control;
    
    var allcontrols = c.TraverseDepthFirst(
         x => x, 
         x => x.Controls.OfType<Control>())).ToList();
    

    【讨论】:

      【解决方案4】:
      var merged = (from cc in list
                    from Control control in cc
                    select cc)
                   .ToList();
      

      或(与显式 LINQ 方法调用相同):

      var merged = list.SelectMany(cc => cc.Cast<Control>()).ToList();
      

      [EDIT]反映新添加的嵌套要求:

      static IEnumerable<T> FlattenTree<T>(
          this IEnumerable<T> nodes,
          Func<T, IEnumerable<T>> childrenSelector)
      {
          foreach (T node in nodes)
          {
              yield return node;
              foreach (T child in childrenSelector(node))
              {
                  yield return child;
              }
          }
      }
      
      var merged = list.SelectMany(cc => cc.Cast<Control>())
                       .FlattenTree(control => control.Controls.Cast<Control>())
                       .ToList();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-01-18
        • 1970-01-01
        • 2010-12-05
        • 2010-09-06
        • 1970-01-01
        • 1970-01-01
        • 2011-05-26
        • 2016-04-17
        相关资源
        最近更新 更多