How can I find WPF controls by name or type?

ID : 11315

viewed : 169

Tags : wpfcontrolsfindwpf





Top 5 Answer for How can I find WPF controls by name or type?

vote vote

97

I combined the template format used by John Myczek and Tri Q's algorithm above to create a findChild Algorithm that can be used on any parent. Keep in mind that recursively searching a tree downwards could be a lengthy process. I've only spot-checked this on a WPF application, please comment on any errors you might find and I'll correct my code.

WPF Snoop is a useful tool in looking at the visual tree - I'd strongly recommend using it while testing or using this algorithm to check your work.

There is a small error in Tri Q's Algorithm. After the child is found, if childrenCount is > 1 and we iterate again we can overwrite the properly found child. Therefore I added a if (foundChild != null) break; into my code to deal with this condition.

/// <summary> /// Finds a Child of a given item in the visual tree.  /// </summary> /// <param name="parent">A direct parent of the queried item.</param> /// <typeparam name="T">The type of the queried item.</typeparam> /// <param name="childName">x:Name or Name of child. </param> /// <returns>The first parent item that matches the submitted type parameter.  /// If not matching item can be found,  /// a null parent is being returned.</returns> public static T FindChild<T>(DependencyObject parent, string childName)    where T : DependencyObject {       // Confirm parent and childName are valid.    if (parent == null) return null;    T foundChild = null;    int childrenCount = VisualTreeHelper.GetChildrenCount(parent);   for (int i = 0; i < childrenCount; i++)   {     var child = VisualTreeHelper.GetChild(parent, i);     // If the child is not of the request child type child     T childType = child as T;     if (childType == null)     {       // recursively drill down the tree       foundChild = FindChild<T>(child, childName);        // If the child is found, break so we do not overwrite the found child.        if (foundChild != null) break;     }     else if (!string.IsNullOrEmpty(childName))     {       var frameworkElement = child as FrameworkElement;       // If the child's name is set for search       if (frameworkElement != null && frameworkElement.Name == childName)       {         // if the child's name is of the request name         foundChild = (T)child;         break;       }     }     else     {       // child element found.       foundChild = (T)child;       break;     }   }    return foundChild; } 

Call it like this:

TextBox foundTextBox =     UIHelper.FindChild<TextBox>(Application.Current.MainWindow, "myTextBoxName"); 

Note Application.Current.MainWindow can be any parent window.

vote vote

83

You can also find an element by name using FrameworkElement.FindName(string).

Given:

<UserControl ...>     <TextBlock x:Name="myTextBlock" /> </UserControl> 

In the code-behind file, you could write:

var myTextBlock = (TextBlock)this.FindName("myTextBlock"); 

Of course, because it's defined using x:Name, you could just reference the generated field, but perhaps you want to look it up dynamically rather than statically.

This approach is also available for templates, in which the named item appears multiple times (once per usage of the template).

vote vote

72

You can use the VisualTreeHelper to find controls. Below is a method that uses the VisualTreeHelper to find a parent control of a specified type. You can use the VisualTreeHelper to find controls in other ways as well.

public static class UIHelper {    /// <summary>    /// Finds a parent of a given item on the visual tree.    /// </summary>    /// <typeparam name="T">The type of the queried item.</typeparam>    /// <param name="child">A direct or indirect child of the queried item.</param>    /// <returns>The first parent item that matches the submitted type parameter.     /// If not matching item can be found, a null reference is being returned.</returns>    public static T FindVisualParent<T>(DependencyObject child)      where T : DependencyObject    {       // get parent item       DependencyObject parentObject = VisualTreeHelper.GetParent(child);        // we’ve reached the end of the tree       if (parentObject == null) return null;        // check if the parent matches the type we’re looking for       T parent = parentObject as T;       if (parent != null)       {          return parent;       }       else       {          // use recursion to proceed with next level          return FindVisualParent<T>(parentObject);       }    } } 

Call it like this:

Window owner = UIHelper.FindVisualParent<Window>(myControl); 
vote vote

66

I may be just repeating everyone else but I do have a pretty piece of code that extends the DependencyObject class with a method FindChild() that will get you the child by type and name. Just include and use.

public static class UIChildFinder {     public static DependencyObject FindChild(this DependencyObject reference, string childName, Type childType)     {         DependencyObject foundChild = null;         if (reference != null)         {             int childrenCount = VisualTreeHelper.GetChildrenCount(reference);             for (int i = 0; i < childrenCount; i++)             {                 var child = VisualTreeHelper.GetChild(reference, i);                 // If the child is not of the request child type child                 if (child.GetType() != childType)                 {                     // recursively drill down the tree                     foundChild = FindChild(child, childName, childType);                     if (foundChild != null) break;                 }                 else if (!string.IsNullOrEmpty(childName))                 {                     var frameworkElement = child as FrameworkElement;                     // If the child's name is set for search                     if (frameworkElement != null && frameworkElement.Name == childName)                     {                         // if the child's name is of the request name                         foundChild = child;                         break;                     }                 }                 else                 {                     // child element found.                     foundChild = child;                     break;                 }             }         }         return foundChild;     } } 

Hope you find it useful.

vote vote

50

If you want to find ALL controls of a specific type, you might be interested in this snippet too

    public static IEnumerable<T> FindVisualChildren<T>(DependencyObject parent)          where T : DependencyObject     {         int childrenCount = VisualTreeHelper.GetChildrenCount(parent);         for (int i = 0; i < childrenCount; i++)         {             var child = VisualTreeHelper.GetChild(parent, i);              var childType = child as T;             if (childType != null)             {                 yield return (T)child;             }              foreach (var other in FindVisualChildren<T>(child))             {                 yield return other;             }         }     } 

Top 3 video Explaining How can I find WPF controls by name or type?







Related QUESTION?