IsReadOnlyProperty.OverrideMetadata中断WPF DataGrid子类中的鼠标双击命令

kkih6yb8  于 2023-05-08  发布在  其他
关注(0)|答案(1)|浏览(154)

我有一个DataGrid的子类,它提供了一些附加功能,并修改了它的一些属性的默认值。有一点特别需要注意的是,我希望网格在默认情况下是只读的,所以我在它的构造函数中设置了IsReadOnly = true
最近,我遇到了一个问题,即在模板中使用网格会导致无论模板中如何设置IsReadOnly都是只读的。查看依赖项属性优先级页面,我得出结论,IsReadOnlyPropertyoverriding metadata是更改其默认值的正确方法:

IsReadOnlyProperty.OverrideMetadata(typeof(NewDataGrid), new FrameworkPropertyMetadata(true));

虽然这解决了控件模板的问题,但似乎会破坏鼠标双击命令绑定:

<DataGrid.InputBindings>
    <MouseBinding Gesture="LeftDoubleClick" Command="{StaticResource DoubleClickCommand}"/>
</DataGrid.InputBindings>

有没有更好的方法来更改IsReadOnly的默认值而不破坏鼠标绑定和/或模板?

7nbnzgx9

7nbnzgx91#

我怀疑您的问题是否与覆盖DataGrid.IsReadOnly属性的默认值有关。只读DataGrid和鼠标输入事件之间没有逻辑关系。
相反,它看起来像鼠标事件是由DataGrid的内部元素(如DataGridCell)处理的,与控件的只读状态无关。例如,双击DataGrid的背景将按预期工作,而单击单元格(或单元格的内容)则不会。
要解决这个问题,我建议覆盖控件的Control.OnMouseDoubleClick和/或Control.OnPreviewMouseDoubleClick方法。
这通常应该是注册事件处理程序之前的第一种方法。首先重写自定义控件或扩展控件的虚拟成员。它会给予你更好的控制,你的代码看起来也更干净。
这是因为,即使重写是虚拟事件调用器(例如Control.OnPreviewMouseDoubleClick),并且控件决定不引发公共关联事件,也总是会调用重写。
因此,不要注册鼠标手势,而是覆盖继承的事件调用器:

public class NewDataGrid : DataGrid
{
  static NewDataGrid() 
    => DataGrid.IsReadOnlyProperty.OverrideMetadata(typeof(MyDataGrid), new FrameworkPropertyMetadata(true));

  protected override void OnMouseDoubleClick(MouseButtonEventArgs e) 
  {
    base.OnMouseDoubleClick(e);

    if (e.LeftButton is MouseButtonState.Pressed)
    {
      // TODO::Handle left double click mouse input
    }
  }

  protected override void OnPreviewMouseDoubleClick(MouseButtonEventArgs e)
  {
    base.OnPreviewMouseDoubleClick(e);

    if (e.LeftButton is MouseButtonState.Pressed)
    {
      // TODO::Handle left double click preview mouse input
    }
  }
}

这与建议的修复程序无关,而是关于原始实现的一般建议:使用StaticResource标记扩展设置MouseBinding.Command的方式看起来很奇怪。命令应该是RoutedCommand,通常定义为static,并在XAML中使用x:Static扩展名引用:

public class NewDataGrid : DataGrid
{
  public static RoutedCommand DoubleClickCommand { get; } = new RoutedUICommand(
    "Raise the tunneling and bubbling MouseDoubleClick event", 
    "DoubleClickCommand", 
    typeof(NewDataGrid));

  public NewDataGrid() 
  {
    var doubleClickCommandBinding = new CommandBinding(DoubleClickCommand, ExecuteDoubleClickCommand, CanExecuteDoubleClickCommand);
    this.CommandBindings.Add(doubleClickCommandBinding); 
  }

  private void CanExecuteDoubleClickCommand(object sender, CanExecuteRoutedEventArgs e) 
    => e.CanExecute = true;

  private void ExecuteDoubleClickCommand(object sender, ExecutedRoutedEventArgs e) 
  {
    var eventArgs = new MouseButtonEventArgs(Mouse.PrimaryDevice, Environment.TickCount, MouseButton.Left);
    OnPreviewMouseDoubleClick(eventArgs);
    OnMouseDoubleClick(eventArgs); 
  }
}
<NewDataGrid.InputBindings>
    <MouseBinding Gesture="LeftDoubleClick" 
                  Command="{x:Static local:NewDataGrid.DoubleClickCommand}" />
</NewDataGrid.InputBindings>

相关问题