Friday, October 24, 2008

Visual Tree Helper Methods

Shown below are two useful methods that works on a VisualTreeHelper class and makes it easy to access elements that are otherwise not easy to access. I would show you concrete examples to use it later, but for now here is the code for the two methods.

   1: public List<T> GetChildrenOfType<T>(DependencyObject parent) where T : DependencyObject


   2: {


   3:    List<T> list = new List<T>();


   4:    int childCount = VisualTreeHelper.GetChildrenCount(parent);


   5:    for (int i = 0; i < childCount; i++)


   6:    {


   7:        DependencyObject child = VisualTreeHelper.GetChild(parent, i);


   8:        //get the current child                 


   9:        if (child is T) list.Add((T)child);


  10:        //if it is of type that you are looking for, then add it to the list        


  11:        list.AddRange(GetChildrenOfType<T>(child)); // on that get a list of children that it has.            


  12:    } 


  13:    return list;



The above method can be used to search for any UIElement given its parent as a parameter. For example, GetChildrenOfType<Button>(StackPanel1) returns a list of all buttons hosted inside the StackPanel. A cut down version of this method is where it just returns the first item.



   1: public T GetChild<T>(DependencyObject parent) where T : DependencyObject


   2: {


   3:     //if(parent is Label) return parent;             


   4:     int childCount = VisualTreeHelper.GetChildrenCount(parent);


   5:     for (int i = 0; i < childCount; i++)


   6:     {


   7:         DependencyObject child = VisualTreeHelper.GetChild(parent, i);


   8:         if (child is T) return (T)child;


   9:         T childLabel = GetChild<T>(child);


  10:         if (childLabel != null) return childLabel;


  11:     } return default(T);


  12: }



The method is again easy to use.





So where did I use these methods? Working with TreeView?





How do I expand a TreeView completely?

This not a straight-forward issue since we know that most of the UI in WPF is virtualized unless otherwise specified. So I have a tree view and I would to completely expand the list. So how do I do it? What are the issues? If you set the TreeView IsExpanded property to true, it only expands the first level of children. So we need to repeat the process again on the children of the just appeared children. But they are not in the Visual Tree unless the lay out is updated. The method shown below works great to toggle expand/collapse of a tree view.









   1: private void ToggleButton_Click(object sender, RoutedEventArgs e)        


   2: {            


   3:          ToggleExpandCollapse(tvQueries); //start toggling with the parent.        


   4: }        


   5:  


   6: private void ToggleExpandCollapse(DependencyObject dO)        


   7: {           


   8:            foreach (TreeViewItem ti in GetChildrenOfType<TreeViewItem>(dO))            


   9:            {             


  10:                ti.IsExpanded = !ti.IsExpanded; //toggle expanded property.            


  11:                // update the layout such that Visual Tree gets updated       


  12:                tvQueries.UpdateLayout(); 


  13:                //now repeat the toggling on the current TreeViewItem            


  14:                ToggleExpandCollapse(ti);               


  15:            }       


  16: } 



Update


Bea just posted a simpler way to do this.






   1: <Style TargetType="TreeViewItem"> 


   2:           <Setter Property="IsExpanded" Value="True" /> 


   3: </Style>


No comments: