WPF学习之路--路由事件

前景简介

博主本人从事SDK开发,主要语言C++,由于客户需求,需要给予自己的SDK,开发一套应用,采用WPF,本人WPF小白。

所以从头开始学习WPF,主要看过了《深入迁出WPF》,就开始了程序的开发,由于对于MVVM理解不深,程序框架写的非常乱,

虽然应用已经发布,但是后续扩展难度较大

最近研究多屏幕显示,发现对于WPF学习,依然停留在表面,所以决定深入学习WPF。

言归正传

博主决定首先跟随 

http://www.cnblogs.com/hegezhou_hot/archive/2012/10/19/2731148.html

的章节一节一节的将基础知识夯实。然后计划花费一定时间看一下《WPF编程宝典》,这本书真心太厚。。。。

由于博主对于XMAL和依赖项属性基本已经了解,所以这里直接跳过。

第一章首先了解WPF的路由事件

路由事件主要包含以下三种事件

  • 冒泡:针对事件源调用事件处理程序。冒泡事件是由源事件,沿着元素树向上传播,路由到后续父元素。大部分路由事件都是采用冒泡事件作为路由策略。冒泡路由事件通常用来报告来自不同控件或其他 UI 元素的输入或状态变化。
  • 直接:只有源元素本身才有机会调用处理程序以进行响应。这与 Windows 窗体用于事件的“路由”相似。但是,与标准 CLR 事件不同的是,直接路由事件支持类处理(类处理将在下一节中介绍 command)而且可以由 EventSetter 和 EventTrigger 使用。
  • 在元素树的根处调用事件处理程序。随后,路由事件将朝着路由事件的源节点元素(即引发路由事件的元素)方向,沿路由线路传播到后续的子元素。在合成控件的过程中通常会使用或处理隧道路由事件,这样,就可以有意地禁止显示复合部件中的事件,或者将其替换为特定于整个控件的事件。在 WPF 中提供的输入事件通常是以隧道/冒泡对实现的。隧道事件有时又称作 Preview 事件,这是由隧道/冒泡对所使用的命名约定决定的。

在程序开发时,通常我们需要为每个事件绑定事件处理程序,但是在某些特定的场景,多个事件可以使用同一套处理程序,这时路由事件的强大就体现出来了,我们可以在一组事件的父元素统一处理这类事件。

        private void btnTest1_Click_1(object sender, RoutedEventArgs e)
        {
            string str = string.Format("orsource{0} 
 soruce{1} 
 sender{2}", e.OriginalSource.GetType().FullName,
                e.Source.GetType().FullName, sender.GetType().FullName);
            MessageBox.Show(str);

            Button btn = e.Source as Button;
            if(null != btn)
            {
                MessageBox.Show((string)btn.Content);
            }
        }

  我们可以通过GetType方法获取当前调用者的类型,运行会发现,事件的源类型是Button类型,父类型是Grid,也就是Button的单击事件路由到了Grid然后由Grid的单击事件监听到。

image

 盗取一张说的比较详细的图片,从这张图片上可以看出节点之间的包含关系。

引用MSDN的解释图,在来看下路由事件

                     事件的处理顺序如下所示:

    1. 针对根元素处理 PreviewMouseDown(隧道)。

    2. 针对中间元素 1 处理 PreviewMouseDown(隧道)。

    3. 针对源元素 2 处理 PreviewMouseDown(隧道)。

    4. 针对源元素 2 处理 MouseDown(冒泡)。

    5. 针对中间元素 1 处理 MouseDown(冒泡)。

    6. 针对根元素处理 MouseDown(冒泡)。

              我们来验证下,我们以此处理所有的preview事件,看看是不是按照上面介绍的方式去处理的。

 

我们分别在Grid和Button增加鼠标左键按下预处理事件(隧道事件,由父事件向下传播),可测可以看出首先执行的是Grid的事件,然后才会去执行Button的事件。

如果父类事件增加对路由事件的返回,Button就不会监听到鼠标左键按下事件

        private void Grid_PreviewMouseLeftButtonDown_1(object sender, MouseButtonEventArgs e)
        {
            MessageBox.Show("Grid_PreviewMouseLeftButtonDown_1");

            e.Handled = true;
        }

  这时Button就不会监听到鼠标左键按下的时间,因为隧道事件返回了。

原文地址:https://www.cnblogs.com/WalkerBlog/p/7565402.html