我有一个 DataGrid 的子类,它提供了一些额外的功能并修改了它的一些属性的默认值。特别的一件事是我希望网格默认是只读的,所以我在它的构造函数中设置了
IsReadOnly = true
。
最近,我遇到了一个问题,即在模板中使用网格导致它是只读的,无论在模板中如何设置
IsReadOnly
。查看 dependency property precedence 页面,我得出的结论是 overriding metadata for IsReadOnlyProperty
是更改其默认值的正确方法:
IsReadOnlyProperty.OverrideMetadata(typeof(NewDataGrid), new FrameworkPropertyMetadata(true));
虽然这解决了控件模板的问题,但它似乎破坏了鼠标双击命令绑定:
<DataGrid.InputBindings>
<MouseBinding Gesture="LeftDoubleClick" Command="{StaticResource DoubleClickCommand}"/>
</DataGrid.InputBindings>
有没有更好的方法来更改
IsReadOnly
的默认值而不破坏鼠标绑定和/或模板?
我怀疑您的问题与覆盖
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
}
}
}
这与推荐的修复程序无关,而是关于您的原始实施的一般建议:您使用
MouseBinding.Command
标记扩展设置 StaticResource
的方式看起来很奇怪。该命令应该是 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>