Now basically there are two questions here, let me just gently introduce you to the problem I'm having at the moment. Let's say we have a regular DataGrid, and I try to apply the PreviewMouseRightButtonDown
on the row for custom functionality and at the same time avoid selection, as this expands the Details view. I thought that this post would help; it was directed at ListView
, but with few adjustment it should work the same, right?
Why would you want to do that?, you may ask.
I want to avoid opening the Details on right click, because in the main project Details section makes a (sometimes) lengthy trip to the database, and right-clicking would only set the appropriate bool
flag-property in the view model in collection.
MainWindowView.xaml:
<DataGrid AutoGenerateColumns="False" RowDetailsVisibilityMode="VisibleWhenSelected">
<!-- Columns ommitted for brevity -->
<DataGrid.ItemContainerStyle>
<Style TargetType="{x:Type DataGridRow}">
<!-- Since I'm using Caliburn Micro anyway, I'm going to redirect the event to view model. It doesn't really matter, issue exists with EventSetter too. -->
<Setter Property="cal:Message.Attach" Value="[Event PreviewMouseRightButtonDown] = [Action CheckItem($eventArgs, $source]"/>
</Style>
</DataGrid.ItemContainerStyle>
</DataGrid>
MainWindowViewModel.cs:
public void CheckItem(RoutedEventArgs args, object source)
{
var row = source as DataGridRow;
if (row != null)
{
var item = (ItemViewModel)row.Item;
item.IsChecked = true;
}
args.Handled = true;
}
Questions time:
- Why is the
RoutingStrategy
on theRoutedEventArgs
listed asDirect
and notTunneling
? I thought allPreview
events wereTunneling
.
- And the more important one: the above solution works if I put a breakpoint inside
CheckItem
, selection does not occur and Details are collapsed, everything works as intended. If I remove the breakpoint though, item is selected and Details section opens as if the event was not stopped from propagating. Why does that happen? I thought that setting theHandled
totrue
on theRoutedEventArgs
should just indicate that the event is really handled.
[EDIT]
Now I've found a 'sleazy' workaround, I can just attach the PreviewMouseDown
event:
bool rightClick;
public void MouseDown(object source, MouseEventArgs args)
{
rightClick = false;
if (args.RightButton == MouseButtonState.Pressed)
{
rightClick = true;
//do the checking stuff here
}
}
and then hook up to SelectionChanged
event:
public void SelectionChanged(DataGrid source, SelectionChangedEventArgs args)
{
if (rightClick)
source.SelectedIndex = -1;
}
It works for my particular case, but subjectively looks very smelly, so I'm open to any other suggestions. Especially why the simple eventArgs.Handled = true
on mouse event is not enough to suppress firing of SelectionChanged
later on :)