4

I have a common task. Implement CheckBox checking in DataGrid by one-click. I deside make a DataGridExtended class, derived from DataGrid, and implement something like that:

XAML:

<DataGrid x:Class="DataGrid.DataGridExtended"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">

</DataGrid>

CODE:

public partial class DataGridExtended : System.Windows.Controls.DataGrid
{
    private int _oldRowIndex;
    private int _oldColumnIndex;

    public DataGridExtended()
    {
        MouseLeftButtonUp += DataGridExtendedMouseLeftButtonUp;
        MouseLeftButtonDown += DataGridExtendedMouseLeftButtonDown;
    }


    private void DataGridExtendedMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        // Если сендер реально DataGridExtended
        var dataGridExt = sender as DataGridExtended;
        if (dataGridExt == null)
            return;

        // Получаем текущую ячейку
        var currentCell = dataGridExt.CurrentCell;

        _oldRowIndex = dataGridExt.SelectedIndex;
        _oldColumnIndex = dataGridExt.CurrentColumn.DisplayIndex;
    }

    private void DataGridExtendedMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        // Если сендер реально DataGridExtended
        var dataGridExt = sender as DataGridExtended;
        if (dataGridExt == null)
            return;

        var rowIndex = dataGridExt.SelectedIndex;
        var columnIndex = dataGridExt.CurrentColumn.DisplayIndex;


        // Получаем текущую ячейку
        var currentCell = dataGridExt.CurrentCell;

        //if (_oldRowIndex != rowIndex || _oldColumnIndex != columnIndex)
        //    return;

        // Получаем текущую колонку
        var currentColumn = currentCell.Column;

        // Получаем контент текущей ячейки
        var cellContent = currentColumn.GetCellContent(currentCell.Item);

        // Если кликнули по чекбоксу
        var checkBox = cellContent as CheckBox;
        if (checkBox == null)
            return;

        // Ставием его в фокус
        checkBox.Focus();

        // Меняем чек на противоположный
        checkBox.IsChecked = !checkBox.IsChecked;

        // Получаем выражение привязки для чекбокса
        var bindingExpression = checkBox.GetBindingExpression(ToggleButton.IsCheckedProperty);

        // Если привязка есть - обновляем ее
        if (bindingExpression != null)
            bindingExpression.UpdateSource();
    }
}

DataGridExtendedMouseLeftButtonUp handler works fine, but DataGridExtendedMouseLeftButtonDown doesn't firing. And that is the problem.

Without DataGridExtendedMouseLeftButtonDown invoking, checking behaviour is not what I want. Namely, checking is working even I move cursor out from grid :E Trying to use PreviewMouseLeftButtonDown instead MouseLeftButtonDown give wrong effect :(

So, how can I solve my problem? Don't offer use different approaches to implement one-click checking plz :) Like using XAML-style for example...

monstr
  • 1,680
  • 1
  • 25
  • 44
  • How does using the `PreviewMouseLeftButtonDown` event 'give wrong effect'? – Sheridan Sep 17 '13 at 09:54
  • When DataGridExtendedMouseLeftButtonDown is invoke, SelectedIndex and CurrentColumn still not initialized. SelectedIndex = -1 CurrentColumn = null but I need correct values to save it as OLD-cell coordinates. – monstr Sep 17 '13 at 10:58
  • You said *Trying to use PreviewMouseLeftButtonDown instead MouseLeftButtonDown give wrong effect*... I'm trying to find out the details behind this statement. – Sheridan Sep 17 '13 at 11:01
  • MouseLeftButtonDown no firing at all - it is a problem. So I tried PreviewMouseLeftButtonDown and it give effect as I describe in my prev comment. – monstr Sep 17 '13 at 11:07
  • I am kind of having same problem. To resolve the single click problem for check box I have added event handler using EventSetter (MouseLeftButtonUp) for targetType="DataGridRow". Usually for first click on each checkBox the event is firing and I am able to set selection for checkbox. However for second click this even is not firing, and checkbox is getting selected/deselected and underneath property remain unchanged. So I don't know why the event is not firing on checkbox for second time. If I click on other cells then event is firing. I tried PreviewMouseLeftButtonUp too. It didn't help. – San Apr 30 '21 at 21:27

2 Answers2

5

In WPF, we often get situations where a particular Click handler appears not to work. The reason for this is usually because a control (or our own code) is handling that event and setting e.Handled = true;, which stops the event from being passed any further. In these situations, it is generally accepted that you should try to access the event before this happens and so we turn to the matching/related Preview event.

In your situation, I would recommend that you use the PreviewMouseLeftButtonDown event. You said that something is not initialized by then, but that doesn't make any sense to me. You said that you need to save the previous value, but you could do that just from your DataGridExtendedMouseLeftButtonUp event handler.

When the user releases the mouse button the first time, then you have their new value. Save this in a variable. When the user releases the mouse button the next and each subsequent time, then save their previous value from the variable as the old value and then read their new value into the variable.

Sheridan
  • 68,826
  • 24
  • 143
  • 183
  • Probably, you don't understand what I want to do. As I told, I need SelectedIndex and CurrentColumn properties initialized when PreviewMouseLeftButtonDown invoked. It is nesessary for I can compare cell row-column coordinates when PreviewMouseLeftButtonDown invoked and PreviewMouseLeftButtonUp invoked. I can make a conclusion whether I came out from the cell or not between these two events. So, your approach does't work for me. Nevermind, I implement single-click check behaviour in another way. – monstr Sep 18 '13 at 05:46
  • @monstr, I understand what you want to do exactly... I think it is you that doesn't understand me, but as you said... never mind. – Sheridan Sep 18 '13 at 07:51
  • Thank you so much `PreviewMouseLeftButtonDown` and `PreviewMouseLeftButtonUp` are working great. –  Nov 16 '21 at 05:55
0

Try MouseDown event and then figure out right or left

HichemSeeSharp
  • 3,240
  • 2
  • 22
  • 44