聊聊WPF继续响应被标记为已处理事件的方法

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

让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:域名申请、网页空间、营销软件、网站建设、猇亭网站维护、网站推广。

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

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

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

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

 
 
 
  1.      
  2.                          
  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.              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  2.              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  3.              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"   
  4.              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   
  5.              mc:Ignorable="d"   
  6.              d:DesignHeight="290" d:DesignWidth="180">  
  7.       
  8.                  
  9.                           
  10.                               
  11.                                   
  12.                                     
  13.                                                  Padding="{TemplateBinding Padding}" MouseLeftButtonDown="MouseLeftButtonDown">  
  14.                                           
  15.                                       
  16.                                   
  17.                               
  18.                           
  19.                         
  20.                           
  21.                               
  22.                                   
  23.                                       
  24.                                           
  25.                                           
  26.                                           
  27.                                       
  28.                                       
  29.                                       
  30.                                       
  31.                                   
  32.                               
  33.                           
  34.                           
  35.                               
  36.                                   
  37.                               
  38.                           
  39.                           
  40.                               
  41.                           
  42.                       
  43.                   
  44.   

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即可。

标题名称:聊聊WPF继续响应被标记为已处理事件的方法
文章出自:http://www.hantingmc.com/qtweb/news38/230088.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联