7

I'm looking for a reliable method to build a list of controls of <Type> contained in a specific <Panel> derived control - this includes those that are direct children, and those which are children of children and so on.

The most obvious way was to just do it recursively:
Add to list any children of this control of <Type>, then repeat function for any child of this control which is a <Panel> or descendant.

However I'm concerned that this won't find all controls in the tree - any ContentControl could also contain of a control of <Type>, as could HeaderedContentControl or any other similar control with one or more child/content attributes.

Is there any means of executing a search against the actual layout tree, so that any instance of a specific type of control contained without a specific parent can be found?

Otto Kanellis
  • 3,629
  • 1
  • 23
  • 24
David
  • 24,700
  • 8
  • 63
  • 83

2 Answers2

20

Here is a fairly naive extension method:-

public static class VisualTreeEnumeration
{
   public static IEnumerable<DependencyObject> Descendents(this DependencyObject root)
   {
     int count = VisualTreeHelper.GetChildrenCount(root);
     for (int i=0; i < count; i++)
     {
       var child = VisualTreeHelper.GetChild(root, i);
       yield return child;
       foreach (var descendent in Descendents(child))
         yield return descendent;
     }
   }
}

This approach does have the draw back that it assumes no changes happen in the tree membership while its in progress. This could be mitigated in use by using a ToList().

Now you can effect your requirements using LINQ:-

 var qryAllButtons = myPanel.Descendents().OfType<Button>();
AnthonyWJones
  • 187,081
  • 35
  • 232
  • 306
  • @AnthonyWJones when i use Descendents no control will retrun for me, i am trace and VisualTreeHelper.GetChildrenCount(root) will return 0 count, why? – Emran Sadeghi Sep 01 '14 at 07:45
1

Let's say you want to find comboboxes inside a userControl which starts with a GRID and has nested grids, stackpanels, canvas etc. containing comboboxes

  1. Imports System.Windows.Controls.Primitives (or Using for C#)
  2. Dim ListOfComboBoxes = MAINGRID.GetVisualDescendants.OfType(Of ComboBox)

That's it...

Otto Kanellis
  • 3,629
  • 1
  • 23
  • 24
  • `GetVisualDescendants` is not in the main Silverlight distribution AFAICT. (Note no simple definition at [MSDN](http://google.com/search?q=GetVisualDescendants+site%3Amsdn.microsoft.com+-site%3Asocial.msdn.microsoft.com).) `System.Windows.Controls.Toolkit` [seems](http://stackoverflow.com/a/7442356/256431) to be required. – Mark Hurd Oct 01 '12 at 02:27
  • System.Windows.Controls.Primitives is a part of System.Windows.Controls in the following directory : c:\Program Files (x86)\Microsoft SDKs\Silverlight\v5.0\Libraries\Client\System.Windows.Controls.dll. – Otto Kanellis Oct 13 '12 at 10:46