编程语言响应被标记为已处理事件的方法

    作者:zls365更新于: 2021-04-26 14:12:56

    大神带你学编程,欢迎选课

    聊聊WPF继续响应被标记为已处理事件的方法。在过去的几十年间,大量的编程语言被发明、被取代、被修改或组合在一起。尽管人们多次试图创造一种通用的程序设计语言,却没有一次尝试是成功的。之所以有那么多种不同的编程语言存在的原因是,编写程序的初衷其实也各不相同;新手与老手之间技术的差距非常大,而且有许多语言对新手来说太难学;还有,不同程序之间的运行成本(runtime cost)各不相同。

    WPF中在冒泡事件或者隧道事件会随其层间关系在visual tree上层层传递,但是,某些事件传递到某些控件是即会”终止“(不再响应相应的注册事件),给人一种事件终结者的印象。

    编程语言响应被标记为已处理事件的方法_编程语言_Python_开发_课课家

    本文转载自微信公众号「CSharp编程大全」,作者zls365 。转载本文请联系CSharp编程大全公众号。

    WPF中在冒泡事件或者隧道事件会随其层间关系在visual tree上层层传递,但是,某些事件传递到某些控件是即会”终止“(不再响应相应的注册事件),给人一种事件终结者的印象。例如:textbox对mousdown事件。

    产生原因:事件处理到达该控件后,其事件对象属性Handled被标记为True。WPF事件引擎在处理控件对应事件时,若检测到该属性为True,就不会调用相应的处理程序。即 WPF路由事件被标记为handled以后, 并不是不在visual tree上传递了;而是,事件引擎不再去调用这个事件的handler了。

    若仍想再其上层元素中(上层是相对事件的传递方向而言)仍然处理响应的事件,解决方式:

    1、若上层控件可以注册相应事件。即没有重写对应控件的Template属性。直接上代码:

    1. "Grid_MouseDown" >     
    2.      Name="txt1" Text="{Binding Path=txt1 ,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" MouseDown="Txt_MouseDown" />                    
    3.  
    1. private void txt_MouseDown(object sender, MouseEventArgs e) 
    2.   { 
    3.      MessageBox.Show("TextMouseDown事件"); 
    4.      e.Handled = false;//使冒泡继续上传 
    5.   } 
    6.  
    7. private void Grid_MouseDown(object sender, MouseEventArgs e) 
    8.   { 
    9.      MessageBox.Show("GridMouseDown事件"); 
    10.   } 

    2、当自定义控件模板时,绑定模版事件不起效,此时用上面的方法不再生效。例如:自定义列表控件模版样式

    1. "Test"  
    2.              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
    3.              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
    4.              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"   
    5.              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   
    6.              mc:Ignorable="d"   
    7.              d:DesignHeight="290" d:DesignWidth="180">  
    8.     name="gridMain">  
    9.                "False" Background="Transparent" ItemsSource="{Binding InfoModel, Mode=OneWay}">  
    10.                           
    11.                             "ItemsControl">  
    12.                                 Name="scrBorder">  
    13.                                     Name="scrollViewer" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"  
    14.                                                  Padding="{TemplateBinding Padding}" MouseLeftButtonDown="MouseLeftButtonDown">  
    15.                                           
    16.                                       
    17.                                   
    18.                               
    19.                           
    20.                         
    21.                           
    22.                               
    23.                                   
    24.                                       
    25.                                         "*"/>  
    26.                                         "Auto"/>  
    27.                                         "Auto"/>  
    28.                                       
    29.                                     "{Binding Desc}" Grid.Column="0"/>  
    30.                                     "{Binding Value}" Margin="0" Grid.Column="1"/>  
    31.                                     "{Binding Unit}" Grid.Column="2" Margin="3,0,15,0"/>  
    32.                                   
    33.                               
    34.                           
    35.                           
    36.                               
    37.                                   
    38.                               
    39.                           
    40.                           
    41.                               
    42.                           
    43.                       
    44.                   
    45.   

     

    ScrollViewer在控件模版中,ScrollViewer的MouseButtonDown事件处理事件如下:断点设置会发现鼠标点击时并不会触发。

    1. private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
    2.    { 
    3.       //e.Handled = false ; 
    4.    } 

    解决办法:UIElement.AddHandler 方法:为指定的路由事件添加路由事件处理程序,并将该处理程序添加到当前元素的处理程序集合中。具体解释详见:httPS://docs.microsoft.com/zh-cn/dotnet/api/system.Windows.uielement.addhandler?f1url=https%3A%2F%2Fmsdn.microsoft.com%2Fquery%2Fdev15.query%3FappId%3DDev15IDEF1%26l%3DZH-CN%26k%3Dk(System.Windows.UIElement.AddHandler);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5);k(DevLang-csharp)%26rd%3Dtrue&view=netframework-4.8

    大体意思:由于WPF事件visual tree上传递过程中,某个元素将该事件标记为已处理,导致事件在传递时不再继续有响应,(原因:Handled被标记为True)如果希望后续元素也能响应此方法,可以使用此方法。

    因此我们可以在上面UserControl的构造函数中添加下面代码:表示gridMain处理相应鼠标点击事件

    1. public UserControl() 
    2.         { 
    3.              InitializeComponent(); 
    4.  
    5.             gridMain.AddHandler(MouseLeftButtonDownEvent, new MouseButtonEventHandler(MouseLeftButtonDown), true); 
    6.        } 

    再次断点调试MouseLeftButtonDown,会发现断点命中。

    AddHandler这个代码的关键点是最后那个true,它告诉WPF引擎相应元素call这个handle,即使它被标记为Handled=true。但是元素处理后其上层元素也照样不会相应,因为handle仍被标记已处理。由此可见,WPF路由事件被标记为handled以后,并不是不在visual tree上传递了;而是,不去call这个handler了。

    上例中如果想要UserControl继续响应,处境就与1一样了,只需将handle标记为false即可。

    编程语言往往使程序员能够比使用机器语言更准确地表达他们所想表达的目的。对那些从事计算机科学的人来说,懂得程序设计语言是十分重要的,因为在当今所有的计算都需要程序设计语言才能完成。

课课家教育

未登录

1