Joan Venge
Joan Venge

Reputation: 331330

How to merge multiple ControlCollections in C#?

Is there an elegant way of doing this? Perhaps with Linq?

For something like this:

List<ControlCollection> list = { ... }

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

EDIT: The final collection will be single dimensional in a sense that all controls will be there, not in a nested way.

Upvotes: 1

Views: 2300

Answers (4)

Pavel Minaev
Pavel Minaev

Reputation: 101615

var merged = (from cc in list
              from Control control in cc
              select cc)
             .ToList();

or (same thing with explicit LINQ method calls):

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

[EDIT] Reflecting the newly added nesting requirement:

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

Upvotes: 0

leppie
leppie

Reputation: 117300

Tree extension method

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

Usage:

Control c = root_form_or_control;

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

Upvotes: 0

Philip Wallace
Philip Wallace

Reputation: 8025

How about this:

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

Usage:

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

This will flatten the control tree:

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

Upvotes: 2

Stephen
Stephen

Reputation: 3621

Linq has Concat and Union methods. Is one of those what you're looking for?

Upvotes: 0

Related Questions