Silverlight路由事件
时间:2010-09-27 来源:JerryT
每个.NET开发者都熟悉事件--当一些东西发生改变的时候,消息将会被一个对象发出(比如Silverlight的元素)来通知你的代码。WPF通过路由事件概念扩展了.NET的事件模型机制。路由事件允许事件起源一个元素,但被另一个元素触发。比如:路由事件允许一个在Shape里触发的点击事件在它被代码处理之前上升到它的容器,然后整个页面。
Silverlight通过一种简单的方式借用了WPF的路由事件模型。WPF支持多种路由事件,Silverlight只支持一种--冒泡路由--事件从容器的内部元素上升到容器本身。另外Silverlight的冒泡事件和一些键盘鼠标事件相关联(像mouseMove和KeyDown)并且仅仅被一些低级的元素支持。就像你看到的那样,Silverlight不对一些高等级的控件事件用冒泡(像Click)。
Silverlight元素的基本事件都继承与两个核心类:UIElement和FrameWorkElement。如图,所有的Silverlight元素都继承与这些类
一些情况下,一些高等级的事件会有效的替换UIElement的一些事件。比如:Button类提供了一个Click事件,当用户按下并释放鼠标或是Button获得了焦点并且用户按下了空格键时触发.所以当处理Button的点击事件时,你应当通过Click事件而不是MouseLeftButtonDown或者MouseLeftButtonUp.相同的TextBox提供了TextChanged事件当Text被除了基本的KeyDown和KeyUp其它事件改变时触发。
事件冒泡
冒泡事件是一种沿着对象树从下到上的事件。例如:MouseLeftButtonDown是冒泡事件。它首先被点击的元素发起,然后被传递到元素的父容器,然后继续传到该容器的父容器,以此类推,知道传到Silverlight元素树的最顶层。
事件冒泡被设计为支持合成——换句话说就是,让你用简单的元素制作出复杂的控件。一个例子就是Silverlight的Content Controls,它可以将一个内嵌的控件当做内容。这些控件通常通过它们提供另一个叫做Content的属性的事实被确认。比如,Button是Content Control。除了可以让它的显示一行字以外,你还可以用一个包含一组元素的StackPanel来填充它,就像这样

<Button BorderBrush="Black" BorderThickness="3" Click="Button_Click">
<StackPanel>
<TextBlock Margin="3" Text="Text and Image" />
<Image Source="happyface.jpg" Stretch="None" />
<TextBlock Margin="3" Text="Courtesy of StackPanel" />
</StackPanel>
</Button>
这里,Content元素是一个包含两汉文字和一张图片的StackPanel。
下图展示了这些XAML形成的Button
这种情况下,Button对它包含的元素的鼠标事件的回应非常重要。换句话说就是,无论用户点击的是Image还是Text或是按钮边框内的一些空白,Buttton.Click事件都应该触发。在每种情况下,你应该用同样的代码作出回应。
当然,你也可以为Button内的所有元素添加上MouseLeftButtonDown和MouseLeftButtonUp事件处理,但是这样会产生大量的无用的代码并且会使你的标记语言维护更困难。事件路由提供了更好的解决方案。
当笑脸被点击时,MouseLeftButtonDown事件首先从Image发起,到StackPanel,然后到Button。Button通过触发自己的Click事件来对MouseLeftButtonDown事件作出响应。
注意:Button的Click事件没有使用事件冒泡。这一点和WPF有所不同。在Silverlight中,只有一小部分基本的底层事件支持事件冒泡。高等级的控件事件不能使用事件冒泡。但是,Button利用MouseLeftButtonDown事件的冒泡的特性来确保它捕捉了任何在它包含元素的上点击。