Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# DataGridColumnHeader内弹出窗口中的奇怪事件行为_C#_Wpf_Datagrid_Wpf Controls - Fatal编程技术网

C# DataGridColumnHeader内弹出窗口中的奇怪事件行为

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

我这里不使用任何外部库,只使用普通WPF

我有一个带有自定义DataGridColumnHeader的DataGrid。此列标题包含用于切换弹出窗口的ToggleButton。在弹出窗口中有一个文本框。我遇到的问题是双击文本框会引发DataGrid上的MouseDoubleClick事件。这是一个包含编号注释的简化版本,我将在后面参考

<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事件)冒泡到数据网格

提前感谢,, David

1)没错,您可以将路由事件的处理程序附加到任何
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事件,所以如果这是一个特例,那么这两个事件不应该是一样的吗?我比预期的要早,它确实有效,所以我已经将它标记为一个答案,因为原始问题已经得到了回答。如果您知道后续问题的答案,如果您也能提供,我们将不胜感激。这是一个“人工”穿越视觉世界的特殊事件