一、什么是逻辑树
逻辑树就是描述WPF界面元素的实际构成,它是由程序在XAML中所有的UI元素组成。最显著的特点就是由布局控件、或者其他常用的控件组成。
<Window x:Class="WpfRouteEvent.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel>
<TextBox></TextBox>
</StackPanel>
</Grid>
</Window>
从上面的代码中可以看出,Window、Grid、StackPanel、TextBox其实就是XAML界面的逻辑树。
二、什么是可视树
可视树是由界面上可见的元素构成的,这些元素主要是由从Visual或者Visual3D类中派生出来的类。
上面代码中的Window、Grid、StackPanel、TextBox它们本身就包含一些由Visual或者Visual3D类派生出的一些可视树的元素来组成的。
三、逻辑树和可视树的遍历
逻辑树遍历使用LogicalTreeHelper类。
可视树遍历使用VisualTreeHelper类。
演示遍历逻辑树和可视树
1、XAML界面左边显示逻辑树,右边显示可视树,代码如下:
<Window x:Class="WpfRouteEvent.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DockPanel>
<Button DockPanel.Dock="Top" Click="Button_Click" Content="获取逻辑树和可视树"></Button>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<DockPanel Grid.Column="0">
<TextBlock DockPanel.Dock="Top" Text="逻辑树"></TextBlock>
<TreeView Name="tvLogicTree"></TreeView>
</DockPanel>
<DockPanel Grid.Column="1">
<TextBlock DockPanel.Dock="Top" Text="可视树"></TextBlock>
<TreeView Name="tvVisualTree"></TreeView>
</DockPanel>
</Grid>
</DockPanel>
</Grid>
</Window>
2、添加类,用于遍历整个XAML界面的逻辑树和可视树
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace WpfRouteEvent
{
public class WpfTreeHelper
{
static string GetTypeDescription(object obj)
{
return obj.GetType().FullName;
}
/// <summary>
/// 获取逻辑树
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static TreeViewItem GetLogicTree(DependencyObject obj)
{
if (obj == null)
{
return null;
}
//创建逻辑树的节点
TreeViewItem treeItem = new TreeViewItem {Header=GetTypeDescription(obj),IsExpanded=true };
//循环遍历,获取逻辑树的所有子节点
foreach (var child in LogicalTreeHelper.GetChildren(obj))
{
//递归调用
var item = GetLogicTree(child as DependencyObject);
if (item != null)
{
treeItem.Items.Add(item);
}
}
return treeItem;
}
/// <summary>
/// 获取可视树
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static TreeViewItem GetVisualTree(DependencyObject obj)
{
if (obj == null)
{
return null;
}
TreeViewItem treeItem = new TreeViewItem { Header=GetTypeDescription(obj),IsExpanded=true};
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
var child = VisualTreeHelper.GetChild(obj, i);
var item = GetVisualTree(child);
if (item != null)
{
treeItem.Items.Add(item);
}
}
return treeItem;
}
}
}
3、在按钮的点击事件中将获取的逻辑树和可视树添加到XAML界面中
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfRouteEvent
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.tvLogicTree.Items.Add(WpfTreeHelper.GetLogicTree(this));
this.tvVisualTree.Items.Add(WpfTreeHelper.GetVisualTree(this));
}
}
}
4、点击按钮,界面运行效果
到此这篇关于WPF路由事件之逻辑树和可视树遍历的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持编程网。