DataGrid RowDetails 中的按钮需要两次点击,解决方法会中断双击

问题描述 投票:0回答:2

我有一个 DataGrid,其中有一个在 RowDetailsTemplate 中定义的按钮。问题在于,单击按钮时,第一次单击会被 DataGrid 消耗以选择行,因此您需要单击按钮两次。

我已经尝试过此处提供的解决方法:wpf RowDetailsTemplate focus

XAML:

<DataGrid ItemsSource="{Binding SomeCollection}">
    <DataGrid.Resources>
        <Style TargetType="DataGridRow">
            <EventSetter Event="PreviewMouseLeftButtonDown" Handler="SelectRowDetails"/>
            <Setter Property="DetailsVisibility" Value="{Binding HasCanadet, Converter={StaticResource BoolToVis}}"/>Mode=OneWay}"/>
        </Style>
    </DataGrid.Resources>
    ...
    <DataGrid.RowDetailsTemplate>
        <DataTemplate>
             ...
             <Button Command="{Binding SomeCommand}" ... \>
             ...
        </DataTemplate>
    </DataGrid.RowDetailsTemplate>
    ...
<DataGrid>

背后代码:

private void SelectRowDetails(object sender, MouseButtonEventArgs e)
{
    var row = sender as DataGridRow;
    if (row == null)
    {
        return;
    }
    row.Focusable = true;
    row.Focus();

    var focusDirection = FocusNavigationDirection.Next;
    var request = new TraversalRequest(focusDirection);
    var elementWithFocus = Keyboard.FocusedElement as UIElement;
    if (elementWithFocus != null)
    {
        elementWithFocus.MoveFocus(request);
    }
}

这效果很好,但我现在需要检测 DataGrid 行上的双击事件。我通过将 InputBindings 添加到 DataGrid 并将 SelectedItem 作为命令参数传递来完成此操作:

...
<DataGrid.InputBindings>
    <MouseBinding MouseAction="LeftDoubleClick" Command="{Binding AnotherCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=SelectedItem}" />
</DataGrid.InputBindings>
...

问题是,仅在 RowDetails 上检测到双击(这很好),但在双击行本身时未检测到双击(这不是)。

有什么想法吗? 谢谢。

c# wpf datagrid
2个回答
3
投票

检查事件源是否为 DataGridDetailsPresenter

类型
private void SelectRowDetails(object sender, MouseButtonEventArgs e)
{
    if(e.Source is DataGridDetailsPresenter) // Like this
    {
        var row = sender as DataGridRow;
        if (row == null)
        {
            return;
        }
        row.Focusable = true;
        row.Focus();

        var elementWithFocus = Keyboard.FocusedElement as UIElement;
        if (elementWithFocus != null)
        {
            elementWithFocus.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
        }
    }            
}

0
投票

1) 为 DataGrid 创建行为

公共静态类DataGridRowFocusBehavior { 公共静态只读 DependencyProperty MouseLeftButtonDownCommandProperty = DependencyProperty.RegisterAttached( "鼠标左键按下命令", 类型(ICommand), typeof(DataGridRowFocusBehavior), 新 UIPropertyMetadata(null, OnMouseLeftButtonDownCommandChanged));

public static ICommand GetMouseLeftButtonDownCommand(DependencyObject obj)
{
    return (ICommand)obj.GetValue(MouseLeftButtonDownCommandProperty);
}

private static void OnMouseLeftButtonDownCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    if (d is not DataGridRow row) return;
    row.PreviewMouseLeftButtonDown -= OnMouseLeftButtonDown;
    row.PreviewMouseLeftButtonDown += OnMouseLeftButtonDown;
}

private static void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    var row = sender as DataGridRow;
    if (row == null) return;

    var command = GetMouseLeftButtonDownCommand(row);
    if (command?.CanExecute(row) == true)
    {
        command.Execute(row);
    }
}

}

2) XAML 更改:使用数据网格行的行为

 <filterDataGrid:FilterDataGrid.RowStyle>
 <Style BasedOn="{StaticResource AdminFilterDataGridExpandedRowStyle}" TargetType="DataGridRow">
     <Setter Property="behavior:DataGridRowFocusBehavior.MouseLeftButtonDownCommand" Value="{Binding DataContext.RowSelectedCommand, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
   
 </Style>

3)查看模型变化

public DelegateCommand RowSelectedCommand { get; private set; }

受保护的 YourViewModel() {

RowSelectedCommand = new DelegateCommand(OnRowSelected);

}

© www.soinside.com 2019 - 2024. All rights reserved.