WPF路由事件一:逻辑树和可视树

一、什么是逻辑树

逻辑树就是描述WPF界面元素的实际构成,它是由程序在XAML中所有的UI元素组成。最显著的特点就是由布局控件、或者其他常用的控件组成。

 1 <Window x:Class="WpfRouteEvent.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         Title="MainWindow" Height="350" Width="525">
 5     <Grid>
 6         <StackPanel>
 7             <TextBox></TextBox>
 8         </StackPanel>
 9     </Grid>
10 </Window>

从上面的代码中可以看出,Window、Grid、StackPanel、TextBox其实就是XAML界面的逻辑树。

二、什么是可视树

可视树是由界面上可见的元素构成的,这些元素主要是由从Visual或者Visual3D类中派生出来的类。

上面代码中的Window、Grid、StackPanel、TextBox它们本身就包含一些由Visual或者Visual3D类派生出的一些可视树的元素来组成的。

三、逻辑树和可视树的遍历

逻辑树遍历使用LogicalTreeHelper类。
可视树遍历使用VisualTreeHelper类。

演示遍历逻辑树和可视树

1、XAML界面左边显示逻辑树,右边显示可视树,代码如下:

 1 <Window x:Class="WpfRouteEvent.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         Title="MainWindow" Height="350" Width="525">
 5     <Grid>
 6         <DockPanel>
 7             <Button DockPanel.Dock="Top" Click="Button_Click" Content="获取逻辑树和可视树"></Button>
 8             <Grid>
 9                 <Grid.ColumnDefinitions>
10                     <ColumnDefinition></ColumnDefinition>
11                     <ColumnDefinition></ColumnDefinition>
12                 </Grid.ColumnDefinitions>
13                 <DockPanel Grid.Column="0">
14                     <TextBlock DockPanel.Dock="Top" Text="逻辑树"></TextBlock>
15                     <TreeView Name="tvLogicTree"></TreeView>
16                 </DockPanel>
17                 <DockPanel Grid.Column="1">
18                     <TextBlock DockPanel.Dock="Top" Text="可视树"></TextBlock>
19                     <TreeView Name="tvVisualTree"></TreeView>
20                 </DockPanel>
21             </Grid>
22         </DockPanel>
23
24     </Grid>
25 </Window>

2、添加类,用于遍历整个XAML界面的逻辑树和可视树

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Windows;
 7 using System.Windows.Controls;
 8 using System.Windows.Media;
 9
10 namespace WpfRouteEvent
11 {
12     public class WpfTreeHelper
13     {
14         static string GetTypeDescription(object obj)
15         {
16             return obj.GetType().FullName;
17         }
18
19         /// <summary>
20         /// 获取逻辑树
21         /// </summary>
22         /// <param name="obj"></param>
23         /// <returns></returns>
24         public static TreeViewItem GetLogicTree(DependencyObject obj)
25         {
26             if (obj == null)
27             {
28                 return null;
29             }
30             //创建逻辑树的节点
31             TreeViewItem treeItem = new TreeViewItem {Header=GetTypeDescription(obj),IsExpanded=true };
32
33             //循环遍历,获取逻辑树的所有子节点
34             foreach (var child in LogicalTreeHelper.GetChildren(obj))
35             {
36                 //递归调用
37                 var item = GetLogicTree(child as DependencyObject);
38                 if (item != null)
39                 {
40                     treeItem.Items.Add(item);
41                 }
42             }
43
44             return treeItem;
45         }
46
47         /// <summary>
48         /// 获取可视树
49         /// </summary>
50         /// <param name="obj"></param>
51         /// <returns></returns>
52         public static TreeViewItem GetVisualTree(DependencyObject obj)
53         {
54             if (obj == null)
55             {
56                 return null;
57             }
58
59             TreeViewItem treeItem = new TreeViewItem { Header=GetTypeDescription(obj),IsExpanded=true};
60
61             for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
62             {
63                 var child = VisualTreeHelper.GetChild(obj, i);
64                 var item = GetVisualTree(child);
65                 if (item != null)
66                 {
67                     treeItem.Items.Add(item);
68                 }
69             }
70
71             return treeItem;
72         }
73     }
74 }

3、在按钮的点击事件中将获取的逻辑树和可视树添加到XAML界面中

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Windows;
 7 using System.Windows.Controls;
 8 using System.Windows.Data;
 9 using System.Windows.Documents;
10 using System.Windows.Input;
11 using System.Windows.Media;
12 using System.Windows.Media.Imaging;
13 using System.Windows.Navigation;
14 using System.Windows.Shapes;
15
16 namespace WpfRouteEvent
17 {
18     /// <summary>
19     /// MainWindow.xaml 的交互逻辑
20     /// </summary>
21     public partial class MainWindow : Window
22     {
23         public MainWindow()
24         {
25             InitializeComponent();
26         }
27
28         private void Button_Click(object sender, RoutedEventArgs e)
29         {
30             this.tvLogicTree.Items.Add(WpfTreeHelper.GetLogicTree(this));
31             this.tvVisualTree.Items.Add(WpfTreeHelper.GetVisualTree(this));
32         }
33     }
34 }

4、点击按钮,界面运行效果

时间: 02-03

WPF路由事件一:逻辑树和可视树的相关文章

WPF路由事件:逻辑树和可视树

一.什么是逻辑树 逻辑树就是描述WPF界面元素的实际构成,它是由程序在XAML中所有的UI元素组成.最显著的特点就是由布局控件.或者其他常用的控件组成. 1 <Window x:Class="WpfRouteEvent.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.c

WPF路由事件二:路由事件的三种策略

一.什么是路由事件 路由事件是一种可以针对元素树中的多个侦听器而不是仅仅针对引发该事件的对象调用处理程序的事件.路由事件是一个CLR事件. 路由事件与一般事件的区别在于:路由事件是一种用于元素树的事件,当路由事件触发后,它可以向上或向下遍历可视树和逻辑树,他用一种简单而持久的方式在每个元素上触发,而不需要任何定制的代码(如果用传统的方式实现一个操作,执行整个事件的调用则需要执行代码将事件串联起来). 路由事件的路由策略: 所谓的路由策略就是指:路由事件实现遍历元素的方式. 路由事件一般使用以下三

[总结]使用WPF路由事件过程中遇到的一些小问题

写在前面 本文一开始会给出一个使用WPF路由事件的实例,因为本文所有的表述都将基于该实例.而本文所给实例来自于<WPF自定义路由事件>一文,在<WPF自定义路由事件>一文中会对实例代码做详细说明,所以,大家在阅读本文实例代码期间若存在疑问,可以先去看看<WPF自定义路由事件>一文,看是否能从中获得你想要的解答. 本文实例 1 新建DetailReportEventArgs类,该类派生自RoutedEventArgs类,RoutedEventArgs类包含与路由事件相关的

WPF路由事件学习转(二)

在传统的.net中已经有了事件机制了,为什么在WPF中要加入路由事件来取代事件呢,最直观的原因就是典型的WPF应用程序使用很多元素关联和组合起来,从而有了两个概念,LogicalTree 和 VisualTree,那么它们分别是什么呢,举个例子: 这就是LogicalTree,一个Grid里面镶嵌了其他控件或布局组件,这相当于一棵树中的叶子.而VisualTree呢?它就是一个树中的叶子里面的结构,用放大镜看一下,其实叶子里面的结构也是一颗树结构,这就是VisualTree了,例如 好了,既然W

理解WPF路由事件

(一)什么时路由事件功能定义:路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对引发该事件的对象)调用处理程序的事件.实现定义:路由事件是一个 CLR 事件,可以由 RoutedEvent 类的实例提供支持并由 Windows Presentation Foundation (WPF) 事件系统来处理(二)路由事件的划分(1)冒泡:针对事件源调用事件处理程序.路由事件随后会路由到后续的父元素,直到到达元素树的根.(2)隧道:最初将在元素树的根处调用事件处理程序.随后,路由事件将朝着路由事件

WPF 路由事件

每每谈到WPF的路由事件,我总是比较模糊的,因为我一般很少用,因为一般是用Binding来满足数据驱动界面的要求,要么就是通过路由命令来执行我想要做的方法,路由事件确实用得少,那么路由事件跟一般的事件的区别在哪里呢?如何使用呢?下面讲揭开其神秘的面纱: 首先说一说事件的历史,在windows操作系统上运行程序,都是消息驱动的,早期Windows API开发和MFC开发的时候可以直接看到各种消息,并且定义消息,到了VB和COM的时代,消息被封装成了事件,到了.NET时代也是事件,但是是直接式的,但

路由事件

基础点 WPF支持直接事件,如 winform样直达事件. 最重要的是wpf支持路由事件,路由是通过"可视树"来传递的,而非逻辑树. 一个事件可以由多个事件处理器来处理(多播),一个事件处理器可以响应多个事件. 一个元素添加了事件侦听器,就不关心是谁触发的. 事件可以由触发元素一层一层向外传递,或由页面最外层一直往里传递,而非由元素开始才向内传. 事件的e.OriginalSource 为事件的可视树为源头,e.Source为逻辑树源头 事件就是定义一个路由事件,然后元素侦听此事件就行

WPF中的Visual Tree和Logical Tree与路由事件

1.Visual Tree和Logical TreeLogical Tree:逻辑树,WPF中用户界面有一个对象树构建而成,这棵树叫做逻辑树,元素的声明分层结构形成了所谓的逻辑树!!Visual Tree:可视树(也叫视觉树),可视树是对逻辑树的扩展,可视树将逻辑树的节点打散,分放到核心棵树组件中,它表述了一些详细的可视化实现,而不是把每个元素当做一个”黑盒“.我们以一个简单的程序来观察下逻辑树与可视树: <Window x:Class="WpfApplication28.MainWind

WPF的路由事件、冒泡事件、隧道事件(预览事件)

原文:WPF的路由事件.冒泡事件.隧道事件(预览事件) 本文摘要: 1:什么是路由事件: 2:中断事件路由: 3:自定义路由事件: 4:为什么需要自定义路由事件: 5:什么是冒泡事件和预览事件(隧道事件): 1:什么是路由事件 WPF中的事件为路由事件,所谓路由事件,MSDN定义如下: 功能定义:路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对引发该事件的对象)调用处理程序的事件. 实现定义:路由事件是一个 CLR 事件,可以由 RoutedEvent 类的实例提供支持并由 Window