How can I find WPF controls by name or type?

后端 未结 18 3050
庸人自扰
庸人自扰 2020-11-21 04:23

I need to search a WPF control hierarchy for controls that match a given name or type. How can I do this?

18条回答
  •  我寻月下人不归
    2020-11-21 05:06

    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.

    /// 
    /// Finds a Child of a given item in the visual tree. 
    /// 
    /// A direct parent of the queried item.
    /// The type of the queried item.
    /// x:Name or Name of child. 
    /// The first parent item that matches the submitted type parameter. 
    /// If not matching item can be found, 
    /// a null parent is being returned.
    public static T FindChild(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(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(Application.Current.MainWindow, "myTextBoxName");
    

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

提交回复
热议问题