一、什么是逻辑树

逻辑树就是描述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="" Width="">
<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="" Width="">
<Grid>
<DockPanel>
<Button DockPanel.Dock="Top" Click="Button_Click" Content="获取逻辑树和可视树"></Button>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<DockPanel Grid.Column="">
<TextBlock DockPanel.Dock="Top" Text="逻辑树"></TextBlock>
<TreeView Name="tvLogicTree"></TreeView>
</DockPanel>
<DockPanel Grid.Column="">
<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 = ; 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路由事件一:逻辑树和可视树的更多相关文章

  1. WPF学习(4)逻辑树和可视树

    前面几节说了一些WPF的基础,包括XAML和布局等.在接下来的几节,我们来说说WPF的核心概念,包括逻辑树和可视树.依赖对象和依赖属性.路由事件.命令这几个部分.本节介绍下逻辑树(Logical Tr ...

  2. WPF自学入门(三)WPF路由事件之内置路由事件

    有没有想过在.NET中已经有了事件机制,为什么在WPF中不直接使用.NET事件要加入路由事件来取代事件呢?最直观的原因就是典型的WPF应用程序使用很多元素关联和组合起来,是否还记得在WPF自学入门(一 ...

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

    一.什么是路由事件 路由事件是一种可以针对元素树中的多个侦听器而不是仅仅针对引发该事件的对象调用处理程序的事件.路由事件是一个CLR事件. 路由事件与一般事件的区别在于:路由事件是一种用于元素树的事件 ...

  4. WPF路由事件学习(一)

    路由事件与一般事件的区别在于:路由事件是一种用于元素树的事件,当路由事件触发后,它可以向上或向下遍历可视树和逻辑树,他用一种简单而持久的方式在每个元素上触发,而不需要任何定制的代码(如果用传统的方式实 ...

  5. WPF 路由事件 Event Routing

    原文:WPF 路由事件 Event Routing 1.路由事件介绍 之前介绍了WPF的新的依赖属性系统,本篇将介绍更高级的路由事件,替换了之前的.net普通事件.相比.net的事件,路由事件具有更强 ...

  6. WPF 自定义一个控件,当点击按钮是触发到ViewModel(业务逻辑部分)和Xaml路由事件(页面逻辑部分)

    #region - 用于绑定ViewModel部分 - public ICommand Command { get { return (ICommand)GetValue(CommandPropert ...

  7. WPF路由事件三:自定义路由事件

    与依赖项属性类似,WPF也为路由事件提供了WPF事件系统这一组成.为一个类型添加一个路由事件的方式与为类型添加依赖项属性的方法类似,添加一个自定义路由事件的步骤: 一.声明路由事件变量并注册:定义只读 ...

  8. WPF 路由事件总结

    1.什么是路由事件 已下为MSDN中的定义 功能定义:路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对引发该事件的对象)调用处理程序的事件. 实现定义:路由事件是一个 CLR 事件,可以由 R ...

  9. WPF自学入门(四)WPF路由事件之自定义路由事件

    在上一遍博文中写到了内置路由事件,其实除了内置的路由事件,我们也可以进行自定义路由事件.接下来我们一起来看一下WPF中的自定义路由事件怎么进行创建吧. 创建自定义路由事件分为3个步骤: 1.声明并注册 ...

随机推荐

  1. C# 打开钱箱支持北洋、佳博、爱普生

    /// <summary> /// 执行开钱箱操作 /// 没钱箱或打印机原功能都可以正常使用 /// </summary> public void ExecuteOpenCa ...

  2. Linux基础之常用命令篇

    一.命令的基本格式 [root@localhost~] root为用户名 -表示当前所在位置 localhost主机名 ‘#’超级用户 '$" 普通用户 命令的基本格式: 命令 [选项] [ ...

  3. .net mvc前台如何接收和解析后台的字典类型的数据 二分搜索算法 window.onunload中使用HTTP请求 网页关闭 OpenCvSharp尝试 简单爬虫

    .net mvc前台如何接收和解析后台的字典类型的数据   很久没有写博客了,最近做了一个公司门户网站的小项目,其中接触到了一些我不会的知识点,今日事情少,便记录一下,当时想在网上搜索相关的内容,但是 ...

  4. Shlwapi.h头文件的使用

    // TestShlwAPI.cpp : 定义控制台应用程序的入口点.// #include "stdafx.h"#include <Shlwapi.h>#pragma ...

  5. 内存管理算法--Buddy伙伴算法【转】

    转自:http://blog.csdn.net/orange_os/article/details/7392986 Buddy算法的优缺点: 1)尽管伙伴内存算法在内存碎片问题上已经做的相当出色,但是 ...

  6. CentOS7添加开机启动服务/脚本(延用CentOS6方法)

    一.添加开机自启服务 在centos7中添加开机自启服务非常方便,只需要两条命令(以Jenkins为例): systemctl enable jenkins.service #设置jenkins服务为 ...

  7. centos7 SSH链接不上

    我试了下面的方法不行--(并且也排查了 ssh是正确安装的) [一]关闭selinuxvi /etc/selinux/config 然后reboot重启!!!! [二]关闭防火墙并禁止启动,有能力自己 ...

  8. iptables控制较复杂案例

    场景设定: 管理员:192.168.101.80 公司有三个部门: 工程部:192.168.2.21-192.168.2.20 软件部门:192.168.2.21-192.168.2.30 经理办公室 ...

  9. TCP数据流

    1. 引言 如果按照分组数量计算,约有一半的TCP报文段包含成块数据(如FTP.电子邮件等),另一半则包含交互数据(如telnet和rlogin).如果按照字节计算,则成块数据与交互数据的比例约为90 ...

  10. ajaxfileupload异步上传附件添加參数的方法

    1.js文件 // JavaScript Document jQuery.extend({ createUploadIframe: function(id, uri) { //create frame ...