9

I would like to handled SelectionChanged event in WPF DataGrid element for user interaction/selection only and skip if it's due to binding or other set values. Any idea how I will determine if the Selection is changed by user interaction? Or any alternate event that would do similar task?

dreamcrash
  • 47,137
  • 25
  • 94
  • 117
binyame tiruneh
  • 103
  • 1
  • 5

4 Answers4

15

Maybe try combine SelectionChanged event with PreviewMouseDown event. When user click a row you set some property and in SelectionChanged event handler check if than property was changed.

Sample code XAML:

<DataGrid SelectionChanged="OnSelectionChanged" PreviewMouseDown="OnPreviewMouseDown">
        <!--some code-->          
</DataGrid>

Code behind:

bool isUserInteraction;

private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (isUserInteraction)
    {
        //some code

        isUserInteraction = false;
    }
}

private void OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    isUserInteraction = true;
}
Rafal
  • 1,081
  • 8
  • 10
  • Can anyone think of a reason, why this is not implemented as separate event...? Using MVVM-Pattern the change always fires even on setting the datacontext.... :/ +1 Rafal for this trick' :) – dba Nov 09 '15 at 14:34
  • 1
    I think this will fail in a lot of cases: (1) if the user clicked in a way that didn't result in a selection change (e.g. clicking an already selected row, or using modifiers, or different mouse buttons), then the selection changes due to a binding, the binding will be seen as a user action. (2) If the user uses the keyboard to change the selection, it will not be seen as a user action. – hypehuman Oct 19 '17 at 15:19
3

hi you can use this in xaml:

 <ComboBox x:Name="ComboBoxName" SelectionChanged="ComboBox_SelectionChanged">
                                        <ComboBox.Style>
                                            <Style TargetType="ComboBox">
                                                <Style.Triggers>                                                       
                                                    <Trigger Property="IsDropDownOpen" Value="True">
                                                        <Setter Property="IsEditable" Value="True"></Setter>
                                                    </Trigger>
                                                </Style.Triggers>
                                            </Style>
                                        </ComboBox.Style>
                                    </ComboBox>

and in code behind:

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (!((ComboBox)sender).IsEditable) return;
        //Do Stuff;
    }
luka
  • 605
  • 8
  • 15
  • 2
    Adding another trigger like the one for `IsDropDownOpen` but with event `IsKeyboardFocused` makes sure that dropdown changes via the keyboard are handled as well – Jens.Huehn_at_SlideFab.com Jan 06 '21 at 07:15
  • As @Jens.Huehn_at_SlideFab.com said. And I should suggest using "IsTextSearchEnabled" instead IsEditable, because IsEditable has some side effects (like blocking tab button, and changing the appearance of the control). – Yaakov Shoham Dec 15 '22 at 06:33
0

Another method would be to handle the DropDownOpened and DropDownClosed events of the ComboBox. This is slightly better than the Rafal's accepted answer because it prevents the boolean flag getting stuck as true if the user clicked the ComboBox and then clicked somewhere else causing the ComboBox to close without a selection being made. What it doesn't solve, though, is if the ComboBox has keyboard focus and the user taps the up and down arrows to change the selection.

private void Event_ComboBox_DropDownOpened(object sender, EventArgs e)
{
    isUserInteraction = true;
}

private void Event_ComboBox_DropDownClosed(object sender, EventArgs e)
{
    isUserInteraction = false;
}

private void Event_ComboBox_SelectedChanged(object sender, SelectionChangedEventArgs e)
{
    if (isUserInteraction)
    {
        // Do work
    }
}
savetruman
  • 145
  • 7
0

Based on @luka in the responses and @Jens.Huehn_at_SlideFab.com in the comments, this is the best solution I found (without blocking the tab button, or changing the appearance of the control, or other quirks):

<ComboBox SelectionChanged="ComboBox_SelectionChanged"
    ItemsSource="{Binding ...}" SelectedItem="{Binding ...}">
    <ComboBox.Style>
        <Style TargetType="ComboBox">
            <Setter Property="IsTextSearchEnabled" Value="False"/>
            <Style.Triggers>
                <Trigger Property="IsDropDownOpen" Value="True">
                    <Setter Property="IsTextSearchEnabled" Value="True"/>
                </Trigger>
                <Trigger Property="IsKeyboardFocused" Value="True">
                    <Setter Property="IsTextSearchEnabled" Value="True"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </ComboBox.Style>
</ComboBox>

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (!((ComboBox)sender).IsTextSearchEnabled) return;
    //Do Stuff;
}
Yaakov Shoham
  • 10,182
  • 7
  • 37
  • 45