PreviewMouseDown 方法在这里有一些示例。
普遍的共识是,将 DataGrid.SelectedItem 反转回其在数据网格的 SelectionChanged 处理程序中的原始值不会按预期工作;所有似乎有效的代码示例都通过要求 Dispatcher 稍后安排它来推迟反转。
您的数据网格上有 CellStyle 吗?对我来说,以下工作:
xml:
<DataGrid.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="DarkSlateBlue"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
代码隐藏:
private void MyDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count > 0)
{
object x = e.AddedItems[0];
if (x is MyObjectType && x != myViewModel.CurrentItem &&
myViewModel.ShouldNotDeselectCurrentItem())
{
// this will actually revert the SelectedItem correctly, but it won't highlight the correct (old) row.
this.MyDataGrid.SelectedItem = null;
this.MyDataGrid.SelectedItem = myViewModel.CurrentItem;
}
}
}
关键是 SelectedCellsChanged 事件在 SelectionChanged 事件之后触发 - 特别是,设置 SelectedItem 不会正确更新只读属性的 SelectedCells,因此需要更多代码隐藏:
private void MyDataGrid_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
{
List<DataGridCellInfo> selectedCells = MyDataGrid.SelectedCells.ToList();
List<MyObjectType> wrongObjects = selectedCells.Select(cellInfo => cellInfo.Item as MyObjectType)
.Where (myObject => myObject != myViewModel.CurrentItem).Distinct().ToList();
if (wrongObjects.Count > 0)
{
MyDataGrid.UnselectAllCells();
MyDataGrid.SelectedItem = null;
MyDataGrid.SelectedItem = myViewModel.CurrentItem;
}
}
显然,处理程序需要连接到数据网格上的相应事件。
这像预期的那样工作,如果需要,可以正确取消选择更改,并且不会产生闪烁。