Fork me on GitHub

UWP 利用VisualTreeHelper查找页面中的元素

一般我们在展示数据的时候,都会采用DataTemplate的预先设置数据模板,再使用Set ItemsSource的方式进行数据绑定

这样就能满足大部分的需求。

不过有时候需要对页面已经展示出来的元素进行调整,这个时候就需要利用UWP自带的VisualTreeHelper来进行查找🔍。

下面列举一些我常用的方法,并且做一些说明和使用范例。

注:有的是从网找摘抄的代码。

 

 

1、FindVisualChild:查找一个页面元素中包含的特定元素

        public static TChild FindVisualChild<TChild>(DependencyObject obj) where TChild : DependencyObject
        {
            if (obj == null) return null;

            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child is TChild found)
                    return found;
                else
                {
                    TChild childOfChild = FindVisualChild<TChild>(child);
                    if (childOfChild != null)
                        return childOfChild;
                }
            }
            return null;
        }

 

代码示例:

从一个页面的Border元素中,查找它其中包裹的TextBlock控件,然后设置各种属性。

var textBlock = TreeHelper.FindVisualChild<TextBlock>(border);
textBlock.Foreground = new SolidColorBrush(Colors.Black);

使用场景:

一个列表中,当鼠标移动到某一个Item上的时候,查找其中的控件,并做一些放大缩小操作等。

 

2、FindVisualChildren:查找页面元素中包含的所有特定元素。这个和上面的类似,只不过返回的是一个List

        public static List<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
        {
            List<T> list = new List<T>();
            if (depObj != null)
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
                {
                    DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
                    if (child != null && child is T)
                    {
                        list.Add((T)child);
                    }

                    List<T> childItems = FindVisualChildren<T>(child);
                    if (childItems != null && childItems.Count() > 0)
                    {
                        foreach (var item in childItems)
                        {
                            list.Add(item);
                        }
                    }
                }
            }
            return list;
        }

 

代码示例:

            var listTextBlock = TreeHelper.FindVisualChildren<TextBlock>(ListView_V);
            foreach (var textblock in listTextBlock)
            {
                textblock.Foreground = new SolidColorBrush(Colors.White);
            }

 

 

3、FindChildByName:根据Name进行查找,前提是你需要在数据模板中设置了Name属性

        public static DependencyObject FindChildByName(DependencyObject parant, string ControlName)
        {
            int count = VisualTreeHelper.GetChildrenCount(parant);

            for (int i = 0; i < count; i++)
            {
                var MyChild = VisualTreeHelper.GetChild(parant, i);
                if (MyChild is FrameworkElement && ((FrameworkElement)MyChild).Name == ControlName)
                    return MyChild;

                var FindResult = FindChildByName(MyChild, ControlName);
                if (FindResult != null)
                    return FindResult;
            }

            return null;
        }

 

代码示例:

            var appBarButton = TreeHelper.FindChildByName(MediaTransportControls_Custom, "CompactOverlayButton") as AppBarButton;
            FontIcon fi = new FontIcon();
            fi.FontFamily = new FontFamily("ms-appx:///Assets/Fonts/VMDL2.ttf#Calculator MDL2 Assets");
            
            if (view.ViewMode == ApplicationViewMode.CompactOverlay)
                fi.Glyph = "\uEE49";
            else
                fi.Glyph = "\uEE47";
            appBarButton.Icon = fi;

注意parent的范围不要太大,否则查找的时间太长,但是一般的应该没问题。

 

4、FindChildrenByName:同上,只不过返回的是一个List而已

        public static List<T> FindChildrenByName<T>(DependencyObject parant, string ControlName) where T : DependencyObject
        {
            List<T> list = new List<T>();
            if (parant != null)
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parant); i++)
                {
                    DependencyObject child = VisualTreeHelper.GetChild(parant, i);
                    if (child != null && child is T && child is FrameworkElement && ((FrameworkElement)child).Name == ControlName)
                    {
                        list.Add((T)child);
                    }

                    List<T> childItems = FindChildrenByName<T>(child, ControlName);
                    if (childItems != null && childItems.Count() > 0)
                    {
                        foreach (var item in childItems)
                        {
                            list.Add(item);
                        }
                    }
                }
            }
            return list;
        }

 

代码示例:

var cardGridList = TreeHelper.FindChildrenByName<Grid>(GridView_Episodes, "Grid_Card");

这个示例是我要从一个GridView控件中找出所有Name为“Grid_Card“的Grid,然后在窗体大小改变的时候,设置每一个Grid的大小。

这样可以做到GridView中动态改变每一个Item的大小了。

 

posted @ 2019-10-15 15:35  猫叔Vincent  阅读(424)  评论(0编辑  收藏  举报