6

The default behaviour of a WPF DataGrid is to select when a row is clicked if SelectionMode="Extended" which is what I want, however I also wish for the row to un-select if it was previously already selected when clicked.

I have tried the following which will unselect the row as soon as it's selected, it seems the row selection occurs before the mouse click event.

private void DoGridMouseLeftButtonUp(object sender, MouseButtonEventArgs args) {
    // Get source row.
    DependencyObject source = (DependencyObject)args.OriginalSource;
    var row = source.FindParent<DataGridRow>();
    if (row == null)
        return;
    // If selected, unselect.
    if (row.IsSelected) {
        row.IsSelected = false;
        args.Handled = true;
    }
}

Where I am binding to this event with the following grid.

<DataGrid SelectionMode="Extended"
          SelectionUnit="FullRow"
          MouseLeftButtonUp="DoGridMouseLeftButtonUp">
Brett Ryan
  • 26,937
  • 30
  • 128
  • 163
  • 1
    shouldnt it be up to the user to unselect the previous selected row? the user can do this by simply click "Ctrl"+"leftMousebutton"? – blindmeis Jun 24 '11 at 08:44
  • I missed the datagrid tag, sorry for that. – Adrian Fâciu Jun 24 '11 at 08:45
  • 1
    @blindmeis - ordinarily that would be fine, however the WPF `DataGrid` is not standard in its behaviour where controls usually require CTRL+CLICK for both addition and removal, `DataGrid` requires CTRL for subtraction only. Our target audience is for simple people who will find it much simpler to just simply click a row to select/unselect. – Brett Ryan Jun 24 '11 at 08:55

2 Answers2

4

I have managed to solve this by instead of handling events on the grid itself to handle them on the cell instead, this involves an event setter for DataGridCell as follows:

<DataGrid SelectionMode="Extended"
          SelectionUnit="FullRow">
    <DataGrid.Resources>
        <Style TargetType="{x:Type DataGridCell}">
            <EventSetter Event="PreviewMouseLeftButtonDown"
                         Handler="DoCheckRow"/>
        </Style>
    </DataGrid.Resources>
    <!-- Column mapping omitted. -->
</DataGrid>

Event handler code.

public void DoCheckRow(object sender, MouseButtonEventArgs e) {
    DataGridCell cell = sender as DataGridCell;
    if (cell != null && !cell.IsEditing) {
        DataGridRow row = FindVisualParent<DataGridRow>(cell);
        if (row != null) {
            row.IsSelected = !row.IsSelected;
            e.Handled = true;
        }
    }
}

My grid is read only so any edit behavior is ignored here.

Brett Ryan
  • 26,937
  • 30
  • 128
  • 163
  • This works, but when I add a Button to a CellTemplate, its event isnt fired because we're setting e.Handled = true. Any idea's how to work around this? – Chris Klepeis Aug 24 '12 at 14:44
  • I was able to solve my problem. Question / answer is here http://stackoverflow.com/a/12113645/71904 – Chris Klepeis Aug 24 '12 at 16:56
  • Excellent, I was thinking of mentioning something similar, I didn't have a windows computer handy to test first though, glad to hear it's working for you. – Brett Ryan Aug 24 '12 at 18:00
0

my wpf datagrid requires CTRL+CLICK for both addition and removal of MULTIPLE rows. so its standard behavior ;) but nevertheless, why you dont use the PreviewMouseDown event and then check for leftmousebutton and Ctrl and do your unselect logic and set e.handled=true?

blindmeis
  • 22,175
  • 7
  • 55
  • 74
  • Odd, I don't need to press CTRL for addition (.NET 4). I will check the preview event tonight, thanks. – Brett Ryan Jun 24 '11 at 09:35
  • well thats strange is use .net4 too and if i want to select every third row for example i need to use CTRL. – blindmeis Jun 24 '11 at 09:40
  • Rasing cancel on `PreviewMouseLeftButtonUp` causes the same behavior as the non preview event where it will unselect right after it was selected. I do have a solution though. – Brett Ryan Jun 27 '11 at 01:20