当前位置: 移动技术网 > IT编程>开发语言>.net > WPF继续响应被标记为已处理事件的方法

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

2020年01月03日  | 移动技术网IT编程  | 我要评论

许谋清,贵妇深藏不露txt,coffee shop音译

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网