wpf 逻辑树与可视化树

摘要:
在WPF中,用户界面是从对象树(称为逻辑树)构建的。因为WPF的几乎每个方面都有与逻辑树相关的行为。与逻辑树类似的概念是可视化树。可视化树基本上是逻辑树的扩展。在可视化树中,节点被分散并分布到核心可视化组件中。例如,虽然ListBox在逻辑上是一个单独的控件,但它的默认视觉呈现由更多原始WPF元素组成:一个Border对象、两个ScrollBar和其他元素。

XAML天生就是用来呈现用户界面的,这是由于它具有层次化的特性。在WPF中,用户界面由一个对象树构建而成,这棵树叫作逻辑树。逻辑树的概念很直观,但是为什么要关注它呢?因为几乎WPF的每一方面(属性、事件、资源等)都有与逻辑树相关联的行为。例如,属性值有时会沿着树自动传递给子元素,而触发的事件可以自底向上或自顶向下遍历树。

与逻辑树类似的一个概念是可视树。可视树基本上是逻辑树的扩展,在可视树中,节点都被打散,分放到核心可视组件中。可视树提供了一些详细的可视化实现,而不是把每个元素当作一个“黑盒”。例如,虽然ListBox从逻辑上讲是一个单独的控件,但它的默认可视呈现是由更多的原始WPF 元素组成的:一个Border对象、两个ScrollBar及其他一些元素。并非所有的逻辑树节点都会出现在可视树中,只有从System.Windows.Media.Visual或System.Windows.Media.Visual3D派生的元素才会被包含进去。其他元素(和一些简单的字符串内容,如代码清单3-1中的内容)不会包含在内,因为它们自己并没有与生俱来的呈现行为。

逻辑树是静态的,不会受到程序员的干扰(例如动态添加/删除元素),但只要用户切换不同的Windows主题,可视树就会改变。

使用System.Windows.LogicalTreeHelper和System.Windows.Media.VisualTreeHelper这两个有些对称的类可以方便地遍历逻辑树和可视树,下边提供两个方法以此遍历wpf中的可视树与逻辑树:

[csharp] view plaincopy
 
  1. private void PrintVisualTree(int depth, DependencyObject obj)  
  2. {  
  3.     Console.WriteLine(depth + " " + obj);  
  4.   
  5.     for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)  
  6.         PrintVisualTree(depth + 1, VisualTreeHelper.GetChild(obj, i));  
  7. }  
[csharp] view plaincopy
 
  1. private void PrintLogicTree(int depth, object obj)  
  2. {  
  3.     Console.WriteLine(depth + " " + obj);  
  4.   
  5.     if (!(obj is DependencyObject))  
  6.         return;  
  7.   
  8.     foreach (object child in LogicalTreeHelper.GetChildren(obj as DependencyObject))  
  9.         PrintLogicTree(depth + 1, child);  
  10. }  

虽然在Window的构造函数中就可以遍历逻辑树,但可视树直到Window完成至少一次布局之后才会有节点,否则是空的。所以遍历可视树需要在控件渲染完再进行遍历,可以在OnContentRendered中进行调用:

[csharp] view plaincopy
 
  1. protected override void OnContentRendered(EventArgs e)  
  2. {  
  3.     base.OnContentRendered(e);  
  4.     PrintVisualTree(0, this);  
  5. }  

免责声明:文章转载自《wpf 逻辑树与可视化树》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Python基础语法三组合数据类型C# 中实现随机时间的获取下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

【opencv基础】OpenCV使用Viz模块3D可视化显示

code bunny.ply /** * @file transformations.cpp * @brief Visualizing cloud in different positions, coordinate frames, camera frustums * @author Ozan Cagri Tonkal */#include <...

(转)Oracle存储过程

Oracle存储过程基本语法 存储过程   1 CREATE OR REPLACE PROCEDURE 存储过程名   2 IS   3 BEGIN   4 NULL;   5 END; 行1:   CREATE OR REPLACE PROCEDURE 是一个SQL语句通知Oracle数据库去创建一个叫做skeleton存储过程, 如果存在就覆盖它; 行...

idea中的后缀补全

IDEA有个很牛逼的功能,那就是后缀补全(Postfix Completion),这个功能可以通过后缀来使用代码补全进行模板式地补全语句,如遍历循环语句(for、foreach)、使用 String.format() 包裹一个字符串、使用类型转化包裹一个表达式、根据判(非)空或者其它判别语句生成 if 语句、用instanceOf生成分支判断语句等。 听起...

WPF 自定义滚动条(ScrollView、ScrollBar)样式【转载】

一、滚动条基本样式 本次修改Scrollview及ScrollBar滚动条样式是通过纯样式实现的。修改的内容包含滚动条的颜色,上下按钮的隐藏。另外添加了鼠标经过滚动条动画。 style样式如下: <!-- ScrollViewer 滚动条 --> <Style x:Key="ScrollBarThumb" TargetType="...

WPF学习笔记——概述

如果你选择WPF,多半原因是因为折服于它那震撼性的用户体验。纵观WPF整个知识体系,其内容并不复杂,但却比较细碎,不易理清。以下内容是对WPF部分内容的简单概括,希望读者能够对WPF框架有个大体认识。 一 常用类型与继承树   WPF的常用类型如下: 二 分辨率无关性   WPF使用设备无关单位度量。一个设备无关单位被定义为1/96英寸。WPF使用下面的...

WPF 显示3D密集场景,堆场管理系统

又好久好久没写博客了,这次接着上文https://www.cnblogs.com/CSSZBB/p/12785380.html,上文用WPF 的绘图功能,制作了一个伪3D的2.5D控件ThreeDBox ,那么这玩意我是用来干啥那?没事做做着玩么? 简单来说,这个东西用来显示密集型的操作画面,比如显示一个堆场里集装箱的摆放情况,是不是稍微有点像了那?当然为...