1

I have a UserControl called ZoneContainer. This has a property that which contains a ListBox containing a number of ListItems. Each ListItem contains a DockPanel.

I'm trying to use a the following code to find the children that exist inside ZoneContainer but childrenCount is 0 every time.

var parent = this as DependencyObject; // I can see that this is populated.

int childrenCount = VisualTreeHelper.GetChildrenCount(parent);

Is there another way to find a specific child object inside a list of objects? Ultimately I'm trying to find the DockPanel, but it's not finding any children even though I know they're in the object.

DaveDev
  • 41,155
  • 72
  • 223
  • 385
  • Are you calling this in the constructor of `ZoneContainer`? – Clemens Nov 06 '12 at 10:21
  • @Clemens, yes I am... and I think I can see where your question is going. The objects haven't been created yet? – DaveDev Nov 06 '12 at 12:03
  • Yes, try doing it in a [Loaded](http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.loaded.aspx) event handler. – Clemens Nov 06 '12 at 12:43

3 Answers3

2

The basic problem here is that not all childs are part of the VisualTree
You can find more information about this problem in this articel from Josh Smith

here are my extension to get all Childs

    public static IEnumerable<DependencyObject> getChilds(this DependencyObject parent)
    {
        if (parent == null) yield break;

        //use the logical tree for content / framework elements
        foreach (object obj in LogicalTreeHelper.GetChildren(parent))
        {
            var depObj = obj as DependencyObject;
            if (depObj != null)
                yield return depObj;
        }

        //use the visual tree for Visual / Visual3D elements
        if (parent is Visual || parent is Visual3D)
        {
            int count = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < count; i++)
            {
                yield return VisualTreeHelper.GetChild(parent, i);
            }
        }
    }
WiiMaxx
  • 5,322
  • 8
  • 51
  • 89
1

This is the function I've got lurking in my library. I've never had any trouble with it, but it does have a GetChildrenCount() call in it so if that's not working for you you may have a bigger problem.

Public Shared Function FindVisualChild(Of T As DependencyObject)(ByVal element As DependencyObject) As T
    If element Is Nothing Then
        Return Nothing
    ElseIf TypeOf (element) Is T Then
        Return element
    Else
        Dim count = VisualTreeHelper.GetChildrenCount(element)
        For index As Integer = 0 To count - 1
            Dim child As DependencyObject = VisualTreeHelper.GetChild(element, index)
            If TypeOf (child) Is T Then
                Return child
            Else
                Dim grandchild As T = FindVisualChild(Of T)(child)
                If grandchild IsNot Nothing Then Return grandchild
            End If
        Next
    End If

    Return Nothing
End Function

Usage: x = FindVisualChild(Of DockPanel)(ParentObject)

Yes, I know it's VB. It's about time one of you C# guys had to convert code for once! :)

PaulMolloy
  • 612
  • 6
  • 13
0

I resolved this issue by querying the objects rather than crawling the visual tree.

var header = container.ListBox.Items.Cast<ListBoxItem>()
    .Select(item => (MyType) item.Content)
    .FirstOrDefault(myType => myType.dpHeader.Name == "whatever").dpHeader;
DaveDev
  • 41,155
  • 72
  • 223
  • 385