C# 单击未选中行中WPF Datagrid中未激发的事件

C# 单击未选中行中WPF Datagrid中未激发的事件,c#,wpf,wpfdatagrid,C#,Wpf,Wpfdatagrid,我有一个数据网格(WPF 4),如下所示: <DataGrid Margin="0,0,0,5" VerticalAlignment="Top" Height="192" BorderBrush="#aaa" Background="White" HorizontalAlignment="Left" ItemsSo

我有一个数据网格(WPF 4),如下所示:

<DataGrid   Margin="0,0,0,5" VerticalAlignment="Top" Height="192" 
                            BorderBrush="#aaa" Background="White" 
                            HorizontalAlignment="Left" 
                            ItemsSource="{Binding Namen, Mode=OneWay}" 
                            ScrollViewer.VerticalScrollBarVisibility="Visible"
                            AutoGenerateColumns="False" 
                            ColumnHeaderHeight="24" 
                            SelectionChanged="DataGridAuslaendischeAlteNamen_SelectionChanged">
                    <DataGrid.Columns>
                        <DataGridTextColumn Width="*" Header="Namenseintrag" Binding="{Binding DisplayName, Mode=OneWay}" />
                        <DataGridTextColumn Width="75" Header="gültig von" Binding="{Binding GueltigAb, StringFormat=d, Mode=OneWay}" />
                        <DataGridTextColumn Width="75" Header="gültig bis" Binding="{Binding GueltigBis, StringFormat=d., Mode=OneWay}" />
                        <DataGridTemplateColumn Width="20" IsReadOnly="True">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <Button Style="{DynamicResource CaratRemoveButton}" 
                                            Click="Button_Click" CommandParameter="{Binding}" 
                                            PreviewMouseDown="Button_PreviewMouseDown" 
                                            />
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>
                </DataGrid.Columns>
                </DataGrid>

我遇到的问题是,
DataGridTemplateColumn
的按钮如果未选中其行,则不会触发click事件。因此,我必须单击按钮两次,一次选择其行,然后引发单击事件。 我读到了有关复选框列的类似问题,但显然建议使用模板列。 我测试了使用按钮的PreviewMouseDown事件,它可以工作,但不是我想要的,因为按钮没有遵循它通常的鼠标点击行为


我错过了什么?无论行是否被选中,我如何通过单击一次来获得单击事件?

基本上,除了使用TemplateColumn和自己管理每个MouseeEvent之外,没有其他解决方案

说明:

单击鼠标向下+
MouseUp
,右键。 因此,您的按钮需要能够获得mouseDown+MouseUp事件

但是

默认情况下,wpf的DataGrid的行处理
MouseDown
事件,以便选择执行
MouseDown
操作的行(要在单元格上确认:
MouseDown
并按住mouseButton,您将看到在释放按钮之前选中了该行)

因此,基本上,
MouseDownEvent
在到达按钮之前被处理,从而阻止您使用按钮上的
Click
事件

Microsoft在其文档中告诉我们,在这种情况下,我们应该使用预览类型的事件,但这不适用于click事件,因为您无法使用PreviewClick事件

因此,我能为您找到的唯一解决方案是在您的按钮上同时收听
PreviewMouseDown
PreviewMouseUp
,并模拟他们自己的点击

有点像这样:

Button myButton = new Button();
bool mouseLeftButtonDownOnMyButton;
myButton.PreviewMouseLeftButtonDown += (s, e) => { mouseLeftButtonDownOnMyButton = true; };
myButton.PreviewMouseLeftButtonUp += (s, e) => {
    if (mouseLeftButtonDownOnMyButton)
        myButton.RaiseEvent( new RoutedEventArgs(Button.ClickEvent,myButton));
        mouseLeftButtonDownOnMyButton = false;
    };
myButton.Click += myButtonCLickHandler;
(当然,您需要在xaml模板中翻译)

NB:这是不完整的,您还应该注意当用户在按钮上执行鼠标下移操作,但在执行鼠标下移之前将鼠标移出按钮的情况(在这种情况下,您应该重置
mouseLeftButtonDownOnMyButton
标志)。最好的方法可能是在普通mouseUpEvent(例如在窗口级别)中重置标志,而不是在按钮的按钮中重置标志


编辑:上述代码还允许您管理单击事件,并且对于真实和模拟的单击事件只有一个代码(因此使用RaiseEvent方法),但是如果您不需要此代码,当然,您也可以直接将代码放在PreviewMouseUp部分。

我也遇到了同样的问题-我在模板列上使用了Image,在MouseDown上使用了event,但我必须单击两次。所以我调用了构造函数上的事件处理程序,它对我起了作用

您可以尝试以下方法:

constructor() {
    datagridname.AddHandler(Button.ClickEvent, new RoutedEventHandler(Button_Click), true);
}

另一个解决方案是创建自己的按钮。这样做的一个优点是:您不必为每个按钮连接事件

public class FireOnPreviewButton : Button
{

    #region Constructor

    public FireOnPreviewButton()
    {
        PreviewMouseLeftButtonDown += OnLeftMouseButtonDownPreview;
    }

    #endregion

    #region Event Handler

    private void OnLeftMouseButtonDownPreview(object sender, MouseButtonEventArgs e)
    {
        // Prevent the event from going further
        e.Handled = true;

        // Invoke a click event on the button
        var peer = new ButtonAutomationPeer(this);
        var invokeProv = peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;
        if (invokeProv != null) invokeProv.Invoke();
    }

    #endregion

}

这可能不是您的选项,但将设置为IsReadonly=true为我解决了这个问题。

我意识到这个问题很老,但我与WPF和XAML签订了10年的合同,我遇到了同样的问题,用户必须在datagrid中单击一行两次才能激活鼠标按钮按下事件。这是因为datagrid使用第一次单击来选择行,第二次单击来触发事件。我发现了一个适用于我的应用程序的简单得多的解决方案:

        PreviewMouseLeftButtonDown="MainDataGrid_OnMouseLeftButtonDown"
这会在第一次单击时触发鼠标左键向下事件。这是它在datagrid设置中的外观:

     <DataGrid Name="MainDataGrid" IsSynchronizedWithCurrentItem="True" SelectionMode="Extended" SelectionUnit="FullRow" 
         ...removed other options for brevity
         PreviewMouseLeftButtonDown="MainDataGrid_OnMouseLeftButtonDown"
         ...removed other options for brevity
         RowHeight="30" BorderThickness="0" Background="#99F0F0F0"  Grid.Column="{Binding GridColumn, Mode=TwoWay}" Grid.Row="1">


我用它代替了鼠标按钮。干杯。

为时已晚,但对其他人来说不是

我一直面临着同样的问题,花了将近6个小时寻找解决办法。我不想再让别人浪费时间了。在看到所有可能的答案之后。我就是这样修复的:

我将一个方法绑定到main/parentDataGrid的Loaded事件。方法定义为:

private void FrameworkElement_OnLoaded(object sender, RoutedEventArgs e)
{
    var grid = sender as DataGrid;
    if (grid != null && grid.CurrentItem == null && grid.SelectedItem != null)
    {
        grid.CurrentItem = grid.SelectedItem;
    }
    else if (grid != null) //Fix when IsSynchronizedWithCurrentItem=True
    {
        var selectedItem = grid.SelectedItem;
        grid.CurrentItem = null;
        grid.SelectedItem = null;
        grid.CurrentItem = selectedItem;
        grid.SelectedItem = selectedItem;
    }
}