我有一个 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 上检测到双击(这很好),但在双击行本身时未检测到双击(这不是)。
有什么想法吗? 谢谢。
检查事件源是否为 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));
}
}
}
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);
}