WPF中的SelectionChanged事件是否只能针对用户交互进行处理?

9

我希望能够处理WPF DataGrid元素中的SelectionChanged事件,仅用于用户交互/选择,如果是由于绑定或其他设置值,则跳过该事件。您有什么想法可以确定选定项是否是由用户交互所更改的?或者是否有任何替代事件可以执行类似的任务?


你能展示一些样例代码来说明你想要实现什么吗? - Rohit Vats
4个回答

15

也许尝试将 SelectionChanged 事件与 PreviewMouseDown 事件结合使用。当用户单击一行时,您可以设置某些属性,并在 SelectionChanged 事件处理程序中检查是否更改了该属性。

XAML 示例代码:

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

代码后台:

bool isUserInteraction;

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

        isUserInteraction = false;
    }
}

private void OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    isUserInteraction = true;
}

有人能想到为什么不将其实现为单独的事件吗?使用MVVM模式时,即使设置数据上下文,更改也总是会触发... :/ +1 Rafal这个技巧' :) - dba
1
我认为在很多情况下这种方法会失败:(1) 如果用户以一种没有导致选择更改的方式点击(例如,点击已经选定的行,或使用修改器或不同的鼠标按钮),那么由于绑定而导致的选择更改将被视为用户操作。(2) 如果用户使用键盘来更改选择,它将不会被视为用户操作。 - hypehuman

3

嗨,您可以在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>

在代码后面:

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (!((ComboBox)sender).IsEditable) return;
        //Do Stuff;
    }

2
添加另一个触发器,例如IsDropDownOpen,但使用事件IsKeyboardFocused可以确保通过键盘进行的下拉更改也得到处理。 - Jens.Huehn_at_SlideFab.com
正如@Jens.Huehn_at_SlideFab.com所说。我建议使用“IsTextSearchEnabled”而不是“IsEditable”,因为“IsEditable”具有一些副作用(例如阻止Tab按钮,并更改控件的外观)。 - Yaakov Shoham

0
另一种方法是处理ComboBox的DropDownOpened和DropDownClosed事件。这比Rafal所接受的答案稍微好一点,因为它可以避免当用户点击ComboBox然后点击其他地方导致ComboBox关闭而没有进行选择时布尔标志卡住为 true 的情况。但它无法解决的问题是,如果ComboBox具有键盘焦点并且用户轻敲向上和向下箭头以更改选择。
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
    }
}

0

根据回复中的@luka和评论中的@Jens.Huehn_at_SlideFab.com,这是我找到的最佳解决方案(不阻止标签按钮,也不更改控件的外观或其他怪异行为):

<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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接