There are some examples for the PreviewMouseDown method here.
General agreement is that reversing the DataGrid.SelectedItem back to its original value inside the datagrid's SelectionChanged handler does not work as expected; all code examples that seem to work postpone the reversal by asking the Dispatcher to schedule it later.
Do you have a CellStyle on your datagrid? For me, the following worked:
xaml:
<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>
codebehind:
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;
}
}
}
The point was that the SelectedCellsChanged event fired after the SelectionChanged event -- and in particular, that setting the SelectedItem does not correctly update the SelectedCells which are a read-only property, so more codebehind:
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;
}
}
Obviously, the handlers need to be hooked up to the corresponding events on the data grid.
This worked like expected, properly cancelled the selection change if desired, and did not produce a flicker.