1

I'm building a POS application, and I want the end user to be able to have a toggle selection mode for the datagrid, I.E. they can click on multiple rows and each clicked item will accumulate on the SelectedItems property - also clicking on a row that was already selected will deselect the row. I found this code in another stackoverflow question:

<DataGrid.Resources>
    <Style TargetType="{x:Type DataGridCell}">
        <EventSetter Event="PreviewMouseLeftButtonDown" Handler="DoCheckRow" />
    </Style>
</DataGrid.Resources>

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

That effectively gives me what I want as far as the toggle selection mode, however, when I add a button as a CellTemplate, the buttons command isn't fired when clicked because I'm setting e.Handled = true; in the above code which stops the event bubble. Is there a way that I can accommodate both?

Chris Klepeis
  • 9,783
  • 16
  • 83
  • 149

3 Answers3

1

Maybe you can try putting an AttachedBehavior on your button? This way you take command out of the picture and handle the click event in the AttachedBehavior.

Big Daddy
  • 5,160
  • 5
  • 46
  • 76
  • Good suggestion. I tried an attached behavior as well as just handling the Click event. It doesn't get called. – Chris Klepeis Aug 24 '12 at 15:32
  • 1
    Have a look at this: http://stackoverflow.com/questions/2445106/wpf-two-commands-handlers-one-command – Big Daddy Aug 24 '12 at 16:05
  • Thanks for point me in the right direction! I was able to solve it using hittesting and some helper functions to find the visual child / parent. See my answer – Chris Klepeis Aug 24 '12 at 16:54
1

You could also do this with an checkbox that will toggle selection on corrosponding row.

<DataGrid.RowHeaderTemplate>
   <DataTemplate>
      <CheckBox IsChecked="{Binding Path=IsSelected, Mode=TwoWay,
                           RelativeSource={RelativeSource FindAncestor,
                           AncestorType={x:Type DataGridRow}}}"/>
   </DataTemplate>
</DataGrid.RowHeaderTemplate>
0

I was able to solve it by using some helper functions to find the visual child / parent and some hit testing:

public void DoCheckRow(object sender, MouseButtonEventArgs e)
{
    DataGridCell cell = sender as DataGridCell;
    if (cell != null && !cell.IsEditing)
    {
        DataGridRow row = VisualHelpers.TryFindParent<DataGridRow>(cell);
        if (row != null)
        {
            Button button = VisualHelpers.FindVisualChild<Button>(cell, "ViewButton");

            if (button != null)
            {
                HitTestResult result = VisualTreeHelper.HitTest(button, e.GetPosition(cell));

                if (result != null)
                {
                    // execute button and do not select / deselect row
                    button.Command.Execute(row.DataContext);
                    e.Handled = true;
                    return;
                }
            }

            row.IsSelected = !row.IsSelected;
            e.Handled = true;
        }
    }
}

Granted its not the most elegant solution, but it works with the MVVM pattern that I use.

Chris Klepeis
  • 9,783
  • 16
  • 83
  • 149