Loading

WPF 中的逻辑树(Logical Tree)与可视化元素树(Visual Tree)

一、前言

​ WPF 中有两种“树”:逻辑树(Logical Tree)可视化元素树(Visual Tree)。 Logical Tree 最显著的特点就是它完全由布局组件和控件组成。那么 Visual Tree 是什么呢?

​ 如果我们仔细观察一棵树的树叶,会发现树叶的脉络也像一棵“树”——有自己的基部并向上生长出多级分叉。在 WPF 的 Logical Tree 上,充当“树叶”的一般都是控件,如果我们仔细观察控件,会发现 WPF 控件本身也是一颗由更细微级别的组件(它们不是控件,而是一些可视化组件,派生自 Visual 类)组成的“树”。即当我们把 Logical Tree 延伸至控件的模板(Template)组件级别时,我们得到的就是 Visual Tree。

​ 实际工作中,大多数情况下我们都是在与 Lgical Tree 打交道,如果你的程序需要借助 Visual Tree 来完成一些与业务逻辑(而不是纯表现逻辑)相关的功能,多半是程序设计不良造成的,最好重新考虑逻辑、功能和数据类型方面的设计。

二、两棵“树”的操作

如果在 Logical Tree 上导航或者查找元素,需要借助 LogicalTreeHelper 类的静态方法来实现;如果在 Visual Tree 上,需要借助 VisualTreeHelper 类的静态方法来实现。例如:我们获取一个界面上的整棵逻辑树和可视化树,具体实现如下:

// 可视化树
        StringBuilder visual = new StringBuilder();
        string GetVisualTree(int depth, DependencyObject obj)
        {
            visual.Append($"{new string(' ', depth)}{obj.GetType().Name}\n");

            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                GetVisualTree(depth + 1, VisualTreeHelper.GetChild(obj, i));
            }
            return visual.ToString();
        }
        private void ButtonVisual_OnClick(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(GetVisualTree(0, this), "可视化树", MessageBoxButton.OK, MessageBoxImage.Question);
        }


        // 逻辑树
        StringBuilder logical = new StringBuilder();
        string GetLogicalTree(int depth, object obj)
        {
            logical.Append($"{new string(' ', depth)}{obj.GetType().Name}\n");
            if (!(obj is DependencyObject))
            {
               return logical.ToString();
            }

            //LogicalTreeHelper.GetChildren 获取逻辑树子对象   
            //obj as DependencyObject  将obj转换成 依赖对象  
            foreach (object child in LogicalTreeHelper.GetChildren(obj as DependencyObject))
            {
                GetLogicalTree(depth + 5, child);
            }

            return logical.ToString();
        }

        private void ButtonLogical_OnClick(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(GetLogicalTree(0, this), "逻辑树", MessageBoxButton.OK, MessageBoxImage.Question);
        }

​ 获取的结果具体如下所示:

posted @ 2021-02-06 22:08  Dwaynerbing  阅读(1446)  评论(0编辑  收藏  举报