C# DataGridColumnHeader内弹出窗口中的奇怪事件行为
我这里不使用任何外部库,只使用普通WPF 我有一个带有自定义DataGridColumnHeader的DataGrid。此列标题包含用于切换弹出窗口的ToggleButton。在弹出窗口中有一个文本框。我遇到的问题是双击文本框会引发DataGrid上的MouseDoubleClick事件。这是一个包含编号注释的简化版本,我将在后面参考C# DataGridColumnHeader内弹出窗口中的奇怪事件行为,c#,wpf,datagrid,wpf-controls,C#,Wpf,Datagrid,Wpf Controls,我这里不使用任何外部库,只使用普通WPF 我有一个带有自定义DataGridColumnHeader的DataGrid。此列标题包含用于切换弹出窗口的ToggleButton。在弹出窗口中有一个文本框。我遇到的问题是双击文本框会引发DataGrid上的MouseDoubleClick事件。这是一个包含编号注释的简化版本,我将在后面参考 <Window x:Class="PopupsAreWeird.MainWindow" xmlns="http://schemas.micr
<Window x:Class="PopupsAreWeird.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PopupsAreWeird" xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridColumnHeader">
<!-- 1) This eventhandler is never called -->
<Grid Control.MouseDoubleClick="Grid_MouseDoubleClick_1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0" />
<ToggleButton x:Name="openToggle" Grid.Column="1" Content="Open" />
<Popup IsOpen="{Binding ElementName=openToggle, Path=IsChecked}" StaysOpen="True">
<!-- 2) This eventhandler is always called, and the problem I am having is there regardless of whether I set e.Handled = true in this handler or not -->
<TextBox Width="200" MouseDoubleClick="TextBox_MouseDoubleClick" />
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel Orientation="Vertical">
<!-- 3) This eventhandler is always called, but never should be -->
<DataGrid MouseDoubleClick="DataGrid_MouseDoubleClick">
<DataGrid.Columns>
<DataGridTextColumn Header="Header 1" Width="200" />
</DataGrid.Columns>
</DataGrid>
</StackPanel>
</Window>
1) 我不明白为什么这个处理器从未被调用。这意味着将e.Handled设置为true,以停止向上冒泡到数据网格。虽然Grid没有MouseDoubleClick的定义,但据我所知,我可以将任何事件的EventHandler附加到任何元素(如将ButtonBase.Click附加到Panel元素)。这是不是真的,或者我在这里遗漏了什么特殊情况
3) 我想避免双击事件冒泡到这里,但即使我在eventhandler 2中将e.Handled设置为true,也会调用此eventhandler,而在该处理程序中,e.Handled为false。我假设原因是弹出窗口是在DataGridColumnHeader内部定义的,出于一些奇怪的原因,引发了2个事件,一个用于弹出窗口的树,另一个用于包含Popup元素的树,但这似乎有点荒谬
我知道弹出窗口在WPF中是一种奇怪的东西,但我似乎遗漏了一些明显的东西。是否有任何方法可以实现我想要的,即不让事件(或至少MouseDoubleClick事件)冒泡到数据网格
提前感谢,,
David1)没错,您可以将路由事件的处理程序附加到任何ui元素
。但实际上,弹出窗口
是一个特例。弹出窗口
是一个特殊控件,其行为类似于窗口
。它可以在屏幕上的任何地方弹出,总是呈现在最上面,并且不一定绑定到应用程序本身。这就是为什么它的可视化树与应用程序的可视化树分离<代码>弹出窗口。子项将是一个独立的视觉树由于路由事件将遍历可视树以由任何节点处理,因此在
弹出窗口中的冒泡/隧道路由事件将在该隔离树的根处停止/启动是有意义的。因此,无法在弹出窗口
之外处理源自弹出窗口
的路由事件
3) 短版本:Control.MouseDoubleClick
(和预览版本)是一个行为不同的特殊事件。当事件遍历可视化树时,在路由上的每个ui元素上引发此事件。因此,将Handled
设置为true
无效。
要解决您的问题,您应该处理UIElement.PreviewMousLeftButtonDown
并检查MouseButtonEventArgs.ClickCount
等于2
以检测双击,然后设置Handled=true
或者在处理前检查发送方
或路由事件源
的类型是否不是文本框
(显式事件筛选)
“虽然这个路由事件似乎遵循一个冒泡的路径通过
作为元素树,它实际上是引发的直接路由事件
沿着元素树,按每个ui元素
。如果设置已处理
属性设置为MouseDoubleClick
事件处理程序中的true
,后续
MouseDoubleClick
在Handled
设置为
false
。这是一个更高级别的事件,适用于希望
当用户双击控件并处理
应用程序中的事件
想要处理鼠标双击的控件作者应使用
MouseLeftButtonDown
当ClickCount
等于2时的事件。这将
使已处理的状态在案例中适当传播
元素树中的另一个元素处理事件
控件
类定义了预览鼠标双击
和
MouseDoubleClick
事件,但不是相应的单击事件。要
查看用户是否单击过该控件一次,处理MouseDown
事件(或其对应项之一),并检查是否单击计数
属性值为1
“
你好,谢谢你的回答!我不知怎么错过了文档中的这一部分,感谢您指出这一点。今天晚些时候,我一回来就会试试。不过,我确实有一个澄清问题。在你的答复中,第1点和第3点似乎相互排斥。如果弹出控件内的事件从不在弹出控件外冒泡(这是可以理解的,也是对eventhandler 1的解释),为什么要调用eventhandler 3?这也在弹出窗口之外。这两个都是MouseDoubleClick事件,所以如果这是一个特例,那么这两个事件不应该是一样的吗?我比预期的要早,它确实有效,所以我已经将它标记为一个答案,因为原始问题已经得到了回答。如果您知道后续问题的答案,如果您也能提供,我们将不胜感激。这是一个“人工”穿越视觉世界的特殊事件