Get Child, Parent, or Children Objects in Silverlight

June 17, 2009 18:10 by wjchristenson2

As a programmer, you may have situations where you need a handle to a control to set its property programmatically.  Pretty simple right?  Let’s add some complexity.  What if you are not guaranteed to know exactly where the control resides.  Is it in our Grid at child index 0 or is it in a StackPanel within the Grid?  What if we want to set the background of all Canvas objects on our page to Transparent?

The Silverlight API provides the VisualTreeHelper class to assist with the traversal of the visual object tree.  Silverlight has a logical and visual object tree.  The visual tree is a subset of the logical object tree and is only populated by objects that have rendering implications.  In a general sense, a collection class would not be included in the visual tree however the Grid you are using as your LayoutRoot of your page would be.  The VisualTreeHelper class has 3 methods to assist with the visual object tree: GetChild(), GetChildrenCount(), GetParent().  Their names are self-descriptive and what I’d like to do is create a few recursive helper methods/extensions to these methods that are a bit more powerful.


Helper Method #1: GetParentObject

This method returns the first parent of a given type and/or name of an object’s parent hierarchy.  For instance, let’s say you know that our StackPanel resides somewhere in the bowels of a Grid named LayoutRoot.  To get a handle to LayoutRoot we could do the following:


   1:  Dim g As Grid = GetParentObject(Of Grid)(myStackPanel, "LayoutRoot")

Helper Method #2: GetChildObject

This method returns the first child of a given type and/or name of an object’s child hierarchy.  So let’s take the inverse of the above.  We have a StackPanel named myStackPanel that resides somewhere beneath our Grid LayoutRoot.  The get the handle to myStackPanel we could do the following:


   1:  Dim sp As StackPanel = GetChildObject(Of StackPanel)(Me.LayoutRoot, "myStackPanel")


Helper Method #3: GetChildObjects

This method returns a list collection of all children of a given type and/or name of an object’s child hierarchy.  So let’s say we want all rectangles which reside somewhere on our page.  Again, our page has a Grid named LayoutRoot.  We could get a list collection of all rectangles on the page by making the following call:


   1:  Dim rectangles As List(Of Rectangle) = GetChildObjects(Of Rectangle)(Me.LayoutRoot)


Helper Methods

Below is the actual methods’ code.  I’m also attaching my zipped test solution.


   1:  Module Common
   2:      ''' <summary>
   3:      ''' Navigates up the object's parent hierarchy and returns the first parent match of the specified type and/or object name.
   4:      ''' </summary>
   5:      ''' <typeparam name="T"></typeparam>
   6:      ''' <param name="obj"></param>
   7:      ''' <param name="name"></param>
   8:      ''' <returns></returns>
   9:      ''' <remarks></remarks>
  10:      Public Function GetParentObject(Of T As FrameworkElement)(ByVal obj As DependencyObject, Optional ByVal name As String = "") As T
  11:          Dim parent As DependencyObject = VisualTreeHelper.GetParent(obj)
  12:   
  13:          While parent IsNot Nothing
  14:              If TypeOf parent Is T AndAlso (CType(parent, T).Name = name Or String.IsNullOrEmpty(name)) Then
  15:                  Return CType(parent, T)
  16:              End If
  17:   
  18:              parent = VisualTreeHelper.GetParent(parent)
  19:          End While
  20:   
  21:          Return Nothing
  22:      End Function
  23:   
  24:      ''' <summary>
  25:      ''' Recursively searches an object's child hierarchy and returns the first child match of the specified type and/or object name.
  26:      ''' </summary>
  27:      ''' <typeparam name="T"></typeparam>
  28:      ''' <param name="obj"></param>
  29:      ''' <param name="name"></param>
  30:      ''' <returns></returns>
  31:      ''' <remarks></remarks>
  32:      Public Function GetChildObject(Of T As FrameworkElement)(ByVal obj As DependencyObject, Optional ByVal name As String = "") As T
  33:          Dim child As DependencyObject = Nothing, grandChild As T = Nothing
  34:   
  35:          For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(obj) - 1
  36:              child = VisualTreeHelper.GetChild(obj, i)
  37:   
  38:              If TypeOf child Is T AndAlso (CType(child, T).Name = name Or String.IsNullOrEmpty(name)) Then
  39:                  Return CType(child, T)
  40:              Else
  41:                  grandChild = GetChildObject(Of T)(child, name)
  42:                  If grandChild IsNot Nothing Then Return grandChild
  43:              End If
  44:          Next
  45:   
  46:          Return Nothing
  47:      End Function
  48:   
  49:      ''' <summary>
  50:      ''' Recursively searches an object's child hierarchy and returns the all children that are of the specified type and/or object name.
  51:      ''' </summary>
  52:      ''' <typeparam name="T"></typeparam>
  53:      ''' <param name="obj"></param>
  54:      ''' <param name="name"></param>
  55:      ''' <returns></returns>
  56:      ''' <remarks></remarks>
  57:      Public Function GetChildObjects(Of T As FrameworkElement)(ByVal obj As DependencyObject, Optional ByVal name As String = "") As List(Of T)
  58:          Dim child As DependencyObject = Nothing, childList As List(Of T) = New List(Of T)
  59:   
  60:          For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(obj) - 1
  61:              child = VisualTreeHelper.GetChild(obj, i)
  62:   
  63:              If TypeOf child Is T AndAlso (CType(child, T).Name = name Or String.IsNullOrEmpty(name)) Then
  64:                  childList.Add(CType(child, T))
  65:              End If
  66:   
  67:              childList.AddRange(GetChildObjects(Of T)(child))
  68:          Next
  69:   
  70:          Return childList
  71:      End Function
  72:  End Module

VisualTreeHelper_Soln.zip (589.38 kb)


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Comments