WPF元素之间的关系
视图逻辑树:
说明:
WPF用户界面元素之间有等级关系,这种关系叫逻辑树。一个元素的模板可以有多个元素组成,这个叫做视图树。WPF两个树之间的差距在于对有些问题,你仅仅需要逻辑树,而有些问题都需要。
<Window> <Grid> <Label Content="Label" /> <Button Content="Button" /> </Grid> </Window>
为什么我们需要两种不同的树:
WPF控件由多个较原始的控件组成。例如:按钮(Button)是由边框(Border)、矩形(Rectangle)和内容(Content)组成。它们应该是按钮(Button)的视图子控件。当WPF要显示一个按钮(Button)时,元素本身是不会显示的,但它会遍历它的视图树把它的子元素显示出来。这种等级关系也可用于命中测试和布局。
然而,有时候你并不关注控件模板的边框和形状。主要是因为该模板将会在运行时被取代,从而你不用涉及视图树的结构。你将需要的是一个更丰富的树,它包含着真正的控件,而不是模板部分。这就是逻辑树的表现。
逻辑树:
逻辑树描述的是用户界面元素之间的关系,它主要负责:
- 传承依赖属性的值
- 设定动态资源的引用
- 为绑定查询元素的名称
- 传递路由事件
视图树:
视图树包括每一个逻辑元素的模板中的所有视图元素。它的责任是:
- 显示视图元素
- 设定元素的透明度
- 设定元素的布局和渲染变化
- 设定元素的可用(IsEnable)属性
- 做命中测试
- 关联资源(寻根)
视图树中的寻根编码:
如果用户界面中的子元素要访问父元素中的数据,但你不到这中间有多少代关系。最好的解决方法就是遍历整个树直到找到所需类型的元素。
这是一个比较准确的帮助程序,你几乎不用修改任何地方就能找出来。
代码
public static class VisualTreeHelperExtensions
{
public static T FindAncestor<T>(DependencyObject dependencyObject)
where T : class
{
DependencyObject target = dependencyObject;
do
{
target = VisualTreeHelper.GetParent(target);
}
while (target != null && !(target is T));
return target as T;
}
}
下面的例子演示了怎样使用这个帮助程序。它从this开始直到找出Grid类型的元素为止。如果它到达了树的根元素还没找到,则返回NULL。
var grid = VisualTreeHelperExtensions.FindAncestor<Grid>(this);