我需要在WPF控件层次结构中搜索与给定名称或类型匹配的控件。我该怎么做呢?


当前回答

试试这个

<TextBlock x:Name="txtblock" FontSize="24" >Hai Welcom to this page
</TextBlock>

后面的代码

var txtblock = sender as Textblock;
txtblock.Foreground = "Red"

其他回答

下面是我的代码,通过类型来查找控件,同时控制我们进入层次结构的深度 (maxDepth == 0表示无限深)。

public static class FrameworkElementExtension
{
    public static object[] FindControls(
        this FrameworkElement f, Type childType, int maxDepth)
    {
        return RecursiveFindControls(f, childType, 1, maxDepth);
    }

    private static object[] RecursiveFindControls(
        object o, Type childType, int depth, int maxDepth = 0)
    {
        List<object> list = new List<object>();
        var attrs = o.GetType()
            .GetCustomAttributes(typeof(ContentPropertyAttribute), true);
        if (attrs != null && attrs.Length > 0)
        {
            string childrenProperty = (attrs[0] as ContentPropertyAttribute).Name;
            foreach (var c in (IEnumerable)o.GetType()
                .GetProperty(childrenProperty).GetValue(o, null))
            {
                if (c.GetType().FullName == childType.FullName)
                    list.Add(c);
                if (maxDepth == 0 || depth < maxDepth)
                    list.AddRange(RecursiveFindControls(
                        c, childType, depth + 1, maxDepth));
            }
        }
        return list.ToArray();
    }
}

我可能只是在重复其他人,但我确实有一段漂亮的代码,它用FindChild()方法扩展了DependencyObject类,该方法将按类型和名称获取子对象。只是包含和使用。

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;
    }
}

希望对你有用。

因为这个问题很普遍,它可能会吸引人们去寻找非常琐碎的情况的答案:如果你只想要一个孩子而不是后代,你可以使用Linq:

private void ItemsControlItem_Loaded(object sender, RoutedEventArgs e)
{
    if (SomeCondition())
    {
        var children = (sender as Panel).Children;
        var child = (from Control child in children
                 where child.Name == "NameTextBox"
                 select child).First();
        child.Focus();
    }
}

或者显然的for循环遍历Children。

您还可以使用FrameworkElement.FindName(string)按名称查找元素。

考虑到:

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

在代码隐藏文件中,你可以这样写:

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

当然,因为它是使用x:Name定义的,所以您可以只引用生成的字段,但是您可能希望动态而不是静态地查找它。

这种方法也可用于模板,其中命名项出现多次(每次使用模板一次)。

您可以使用VisualTreeHelper来查找控件。下面是一个使用VisualTreeHelper查找指定类型的父控件的方法。您也可以使用VisualTreeHelper以其他方式查找控件。

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);
      }
   }
}

这样叫它:

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