开发者社区> 煦风满裳> 正文

Silverlight实用窍门系列:35.细解Silverlight冒泡路由事件和注册冒泡路由事件【附带实例源码】

简介:
+关注继续查看

Silverlight中的事件分为普通事件和冒泡路由事件,它并没有包括WPF中的隧道路由事件,在本章中将详细讲解冒泡路由事件和如何注册一个冒泡路由事件。

一、细解冒泡路由事件

冒泡路由事件可以比喻为:一个父对象X包含子对象A,在子对象A中没有事件处理程序,但是父对象X中有一个鼠标左击事件处理程序。当用户点击子孙对象A时,这个事件又鼠标左击冒泡传递到父对象X。父对象的事件处理程序就处理这次点击事件。

总结出来就是:冒泡路由事件是从子孙的元素传递到父对象事件处理程序中进行处理的一种解决方案,直到这个事件传递到最上层根对象。

如果子对象有这类路由事件(如:MouseLeftButtonDown)的处理程序,父对象也有这类路由事件(如:MouseLeftButtonDown)的处理程序的时候,会出现什么情况呢?答案是既执行子对象的MouseLeftButtonDown处理程序,又执行父对象的MouseLeftButtonDown处理程序。如果我们想在某个子对象触发MouseLeftButtonDown路由事件的时候,只让该子对象执行MouseLeftButtonDown处理程序而父对象不执行它的MouseLeftButtonDown处理程序,我们应该如何办呢?答案是设置事件的e.Handled=ture。中止事件的冒泡路由,表示这个事件已经处理完毕,不用继续冒泡往上传递。

现在我们通过一个实例程序来看冒泡路由事件的处理,首先我们来看XAML代码:

<Grid Width="200" Height="200" x:Name="GridA" HorizontalAlignment="Left" Background="AliceBlue"
 MouseLeftButtonDown="LayoutRoot_MouseLeftButtonDown">
 <Ellipse Height="44" HorizontalAlignment="Left" Fill="DarkKhaki" Name="ellipseFirst"
 Stroke="Black" StrokeThickness="1" VerticalAlignment="Top" Width="86" />
 <Ellipse Height="44" HorizontalAlignment="Left" Fill="BlanchedAlmond" Margin="0,71,0,0"
 Name="ellipseSecond" Stroke="Black" StrokeThickness="1" VerticalAlignment="Top"
 Width="94" MouseLeftButtonDown="ellipse2_MouseLeftButtonDown" />
</Grid>

我们为一个名为GridA的Grid对象下添加两个子对象圆,这两个圆的Name分别是ellipseFirst和ellipseSecond,ellipseFirst没有任何的事件处理程序,而ellipseSecond有一个事件处理程序ellipse2_MouseLeftButtonDown,父对象有一个事件处理程序LayoutRoot_MouseLeftButtonDown。
#region 路由事件的原理
 private void LayoutRoot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
 {
 //正在调用事件处理程序的对象
 FrameworkElement grid = sender as FrameworkElement;
 //获取到触发此次事件的对象
 FrameworkElement ellipse = e.OriginalSource as FrameworkElement;
 MessageBox.Show("引发事件的子对象名是:" + ellipse.Name + 
 "----子对象事件冒泡上来触发并且产生事件的父对象名是:" + grid.Name);
 }
 private void ellipse2_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
 { 
 //获取到触发此次事件的对象
 FrameworkElement ellipse = e.OriginalSource as FrameworkElement;
 //通过e.Handled设置为ture表示路由事件已处理拦截了事件,
 //不必冒泡到父对象的LayoutRoot_MouseLeftButtonDown去处理。
 MessageBox.Show("引发事件的对象名是:" + ellipse.Name + ",路由事件被拦截");
 e.Handled = true;
 }
 #endregion

在鼠标左键点击事件中的e.OriginalSource可以获取到触发事件的源对象。

在此实例中,我们点击圆ellipseFirst的时候,它没有任何事件处理程序,于是冒泡路由策略发生作用,此次点击事件由父对象的LayoutRoot_MouseLeftButtonDown事件处理程序进行处理。于是弹出以下界面:

2011041116144886.jpg

当我们点击圆ellipseSecond的时候,它自身有一个事件处理程序,于是首先执行它自身的左键点击处理程序ellipse2_MouseLeftButtonDown,弹出以下界面:

2011041116150429.jpg

二、注册冒泡路由事件

在Silverlight中我们使用UIElement.AddHandler 方法为对象注册冒泡路由事件处理程序。

public void AddHandler( RoutedEvent routedEvent,Delegate handler,bool handledEventsToo)
 //routedEvent 
 // 类型:System.Windows.RoutedEvent
 // 要处理的路由事件的标识符。

 //handler 
 // 类型:System.Delegate
 // 对处理程序实现的引用。

 //handledEventsToo 
 // 类型:System.Boolean
 // 如果为 true,则将按以下方式注册处理程序:即使路由事件在其事件数据中标记为已处理,
 // 也会调用该处理程序;如果为 false,则使用默认条件注册处理程序,
 // 即当路由事件已标记为已处理时,将不调用该处理程序。

下面我们来看一下实例的源码XAML文件代码如下:
<Grid Width="200" Height="200" x:Name="GridB" HorizontalAlignment="Right" Background="Aqua">
 <Ellipse Height="44" HorizontalAlignment="Left" Fill="Coral" Name="ellipseThird" 
 Stroke="Black" StrokeThickness="1" VerticalAlignment="Top" Width="86" />
 <Ellipse Height="44" HorizontalAlignment="Left" Fill="DarkSalmon" Margin="0,71,0,0"
 Name="ellipseFourth" Stroke="Black" StrokeThickness="1" VerticalAlignment="Top"
 Width="94" MouseLeftButtonDown="ellipse2_MouseLeftButtonDown" />
</Grid>

在这里我们创建了一个名为GridB的Grid对象,在GridB对象内部我们创建两个圆分别是ellipseThird和ellipseFourth。其中ellipseFourth中我们添加了一个事件处理程序ellipse2_MouseLeftButtonDown。
#region 为GridB控件添加一个路由事件处理程序,并且设置一直都要处理这个路由事件
 private void UserControl_Loaded(object sender, RoutedEventArgs e)
 {
 //为GridB控件添加一个路由事件处理程序,并且设置一直都要执行此路由事件
 this.GridB.AddHandler(FrameworkElement.MouseLeftButtonDownEvent, 
 new MouseButtonEventHandler(GridB_MouseLeftButtonDown), 
 true);
 }

 private void GridB_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
 {
 //处理这次事件的对象
 FrameworkElement grid = sender as FrameworkElement;
 //获取到触发事件的对象
 FrameworkElement ellipse = e.OriginalSource as FrameworkElement;
 MessageBox.Show("引发事件的子对象名是:" + ellipse.Name +
 "----子对象事件冒泡上来触发并且产生事件的父对象名是:" + grid.Name);
 }
 #endregion


在上一段代码中我们在控件的Loaded事件中为GridB注册了一个事件处理程序名为:GridB_MouseLeftButtonDown。注意我们在使用AddHandle注册这个程序的时候,设置了handledEventsToo为Ture,意味着我们不管子控件(ellipseThird和ellipseFourth)的自身事件处理程序中是否设置e.Handled是否为Ture,我们都要执行父控件的事件处理程序GridB_MouseLeftButtonDown。反之如果我们设置handledEventsToo为False,则根据子控件的e.Handled是否为Ture来决定是否冒泡路由到父控件处理。

下面我们来看看点击ellipseThird的时候弹出以下界面:

2011041116151843.jpg

下面我们来看看点击ellipseFourth的时候,因为设置handledEventsToo为Ture,不管子控件(ellipseThird和ellipseFourth)的自身事件处理程序中是否设置e.Handled是否为Ture,我们都要执行父控件的事件处理程序GridB_MouseLeftButtonDown,所以先后弹出以下两个窗口界面:

2011041116154560.jpg2011041116160160.jpg

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
WPF的路由事件、冒泡事件、隧道事件(预览事件)
原文:WPF的路由事件、冒泡事件、隧道事件(预览事件) 本文摘要: 1:什么是路由事件; 2:中断事件路由; 3:自定义路由事件; 4:为什么需要自定义路由事件; 5:什么是冒泡事件和预览事件(隧道事件); 1:什么是路由事件     WPF中的事件为路由事件,所谓路由事件,MSDN定义如下:     功能定义:路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对引发该事件的对象)调用处理程序的事件。
1196 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,大概有三种登录方式:
9073 0
一些JS事件小片段代码整理收集(持续)
一、js实现 1 2 3 4 5 function AcceptData(num){ 6 document.getElementById("accepDate").value+=num; 7 } 8 9 10 11 12 13 14 15 16  二、input输入框的value传值显示 input输入框中用户输入的值,点击按钮显示在另一个容器之中。
807 0
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
19701 0
一个形象展示浏览器事件冒泡与捕获过程的demo
http://jsbin.com/xafeniyaqu/edit?html,js,output
621 0
as3.0中如何阻止事件冒泡?
as3.0中的事件冒泡机制有时候会很烦人,比如一个Sprite(方便下文描述就命名为Container吧)把另一外Sprite(称为Child吧)做为子元素套进来以后,如果两个Sprite都注册了Mouse_Down事件,要想在Child上点击鼠标时系统只响应Child的Mouse_Down事件,默...
737 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
17990 0
+关注
煦风满裳
程兴亮,专注于C#方面的开发工作,喜欢钻研Silverlight,CIL等方面的知识。平时喜欢看书、写技术博客、摄影、旅游和运动。
32
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载