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


    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

  • 相关阅读:
    EF6学习
    jQuery中each的用法之退出循环和结束本次循环
    Convert.ToInt16(s);int.Parse(s);和(int)s的区别
    .net网站部署winserver2008R2 iis浏览只显示目录浏览
    二维数组按某列排序
    XML文件的操作
    .net中 IOC DI
    .net在Oracle数据库中为In条件查询防止sql注入参数化处理
    测试代码耗时的时间段(.net)
    沙箱测试
  • 原文地址:https://www.cnblogs.com/dearroy/p/12769858.html
Copyright © 2020-2023  润新知