欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-25 18:50:43
WPF继续响应被标记为已处理事件的方法 WPF中在冒泡事件或者隧道事件会随其层间关系在visual tree上层层传递,但是,某些事件传递到某些控件是即会”终止“(不再响应相应的注册事件),给人一种事件终结者的印象。例如:textbox对mousdown事件。 产生原因:事件处理到达该控件后,其事件 ......

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

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

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

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

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

<grid mousedown="grid_mousedown" >    
     <textbox name="txt1" text="{binding path=txt1 ,mode=twoway,updatesourcetrigger=propertychanged}" mousedown="txt_mousedown" />                   
</grid>
 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、当自定义控件模板时,绑定模版事件不起效,此时用上面的方法不再生效。例如:自定义列表控件模版样式

<usercontrol x:class="test"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:ignorable="d" 
             d:designheight="290" d:designwidth="180">
    <grid  name="gridmain">
               <itemscontrol focusable="false" background="transparent" itemssource="{binding infomodel, mode=oneway}">
                        <itemscontrol.template>
                            <controltemplate targettype="itemscontrol">
                                <border x:name="scrborder">
                                    <scrollviewer x:name="scrollviewer" verticalscrollbarvisibility="auto" horizontalscrollbarvisibility="auto"
                                                 padding="{templatebinding padding}" mouseleftbuttondown="mouseleftbuttondown">
                                        <itemspresenter />
                                    </scrollviewer>
                                </border>
                            </controltemplate>
                        </itemscontrol.template>
                      
                        <itemscontrol.itemtemplate>
                            <datatemplate>
                                <grid>
                                    <grid.columndefinitions>
                                        <columndefinition width="*"/>
                                        <columndefinition width="auto"/>
                                        <columndefinition width="auto"/>
                                    </grid.columndefinitions>
                                    <textblock text="{binding desc}" grid.column="0"/>
                                    <textblock text="{binding value}" margin="0" grid.column="1"/>
                                    <textblock text="{binding unit}" grid.column="2" margin="3,0,15,0"/>
                                </grid>
                            </datatemplate>
                        </itemscontrol.itemtemplate>
                        <itemscontrol.itemspanel>
                            <itemspaneltemplate>
                                <stackpanel></stackpanel>
                            </itemspaneltemplate>
                        </itemscontrol.itemspanel>
                        <itemscontrol.itemcontainerstyle>
                            <style>
                                <setter property="control.margin" value="1"/>
                            </style>
                        </itemscontrol.itemcontainerstyle>
                    </itemscontrol>
                </grid>
</usercontrol>

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

 

引用博文:

https://www.cnblogs.com/debuglzq/archive/2013/05/07/3062733.html