电脑技术学习

了解WPF中的路由事件和命令

dn001

WPF元素树

如果您在项目中开启一个新窗口并在设计器中将按钮拖入窗口内,您会得到 XAML 格式的元素树,如下所示(为了清楚略去了属性):

<Window>

<Grid>

<Button/>

</Grid>

</Window>

其 中的每个元素都代表对应 .NET 类型的一个运行时实例,元素的声明分层结构形成了所谓的逻辑树。此外,WPF 中的许多控件不是 ContentControl 就是 ItemsControl,这代表他们可以有子元素。例如,Button 是一个 ContentControl,它可以将复杂的子元素做为其内容。您可以展开逻辑树,如下所示:

<Window>

<Grid>

<Button>

<StackPanel>

<Image/>

<TextBlock/>

</StackPanel>

</Button>

</Grid>

</Window>

生成的 UI 如图 1 所示。


图1包含按钮内容的简单窗口

如 您所想,树可以有多个分支(Grid 中的另一 Button),因此逻辑树会变得极为复杂。对于逻辑树的 WPF 元素,您需要意识到您所见到的并不是您在运行时真正得到的内容。每个这样的元素通常都会在运行时扩展为更为复杂的可视元素树。在本例中,元素的逻辑树扩展 为可视元素树,如图 2 所示。


图2简单窗口可视树

我使用名为 Snoop 的工具 (blois.us/Snoop) 查看图 2 中所示可视树的元素。您可以看到窗口 (EventsWindow) 实际是将其内容置入 Border 和 AdornerDecorator 之内,用 ContentPresenter 显示其中的内容。按钮也与此类似,将其内容置入 ButtonChrome 对象,然后用 ContentPresenter 显示内容。

单 击按钮时,我可能实际根本没有单击 Button 元素,可能是单击可视树中的某一子元素,甚至是逻辑树中未显示的元素(如 ButtonChrome)。例如,假设我在按钮内的图像上方单击鼠标。这一单击操作在一开始实际是将其表达为 Image 元素中的 MouseLeftButtonDown 事件。但却需要转化为 Button 层级的 Click 事件。这就要引入路由事件中的路由。