WPF复选框:处理选中状态变更

66
在 WPF 数据绑定中,我可以将 IsChecked 属性绑定到某些数据(例如用户设置),但是我需要处理“CheckChanged”事件。我知道可以分别处理 Checked 和 Unchecked 事件,但是否有任何方法可以在更改此值时收到通知?

在WPF数据绑定中,我可以将IsChecked属性绑定到某些数据,例如用户设置,但我需要处理“CheckChanged”事件,我知道可以分别处理Checked和Unchecked事件,但是否有任何方法可以在更改此值时得到通知?

<CheckBox Content="Case Sensitive" IsChecked="{Binding bSearchCaseSensitive,
          Source={x:Static Properties:Settings.Default}}" />

注意:我不在乎它是选中还是未选中。我只想在它改变时得到通知。


1
你为什么要那样做?为什么不将 IsChecked 属性绑定到 ViewModel 中的某个属性并对该属性做出反应呢?UI 不是数据。 - Federico Berasategui
它已经绑定到用户设置。UI 不是数据,这与提出的问题有关吗? - David
3
我的观点是,如果 ViewModel 需要知道什么时候发生了变化,你应该将其与 ViewModel 绑定,而不是绑定到静态的东西,然后在 ViewModel 中可以更改这个静态值。 - Federico Berasategui
我不想改变这个值,我希望能够处理值被更改的事件并进行其他操作,例如显示一个消息框。您有什么建议来挂钩这个事件吗? - David
谢谢您的注意。但是我正在尝试看是否有更为简洁的解决方案。 - David
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/26387/discussion-between-david-and-highcore - David
6个回答

122

你可以分别处理已选和未选事件,但这并不意味着你必须这样做。如果您不想遵循MVVM模式,可以将相同的处理程序附加到两个事件,并获得更改信号:

<CheckBox Checked="CheckBoxChanged" Unchecked="CheckBoxChanged"/>

并且在代码后台中;

private void CheckBoxChanged(object sender, RoutedEventArgs e)
{
  MessageBox.Show("Eureka, it changed!");
}
请注意,WPF强烈鼓励使用INotifyPropertyChanged和/或DependencyProperties的MVVM模式,这是有原因的。这是能够工作的东西,而不是我希望鼓励成为良好编程习惯的东西。

38

当复选框被点击时,复选框的更改也会生效:

<CheckBox Click="CheckBox_Click" />
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
    // ... do some stuff
}

它具有额外的优点,即在 IsThreeState="True" 时工作,而仅处理 Checked 和 Unchecked 则不行。


如果复选框被禁用但您点击它会发生什么?我想事件仍然会触发,这不是大多数情况下的期望行为。 - Mario Garcia
1
那不应该发生。如果它被禁用,点击事件也将被禁用。 - Expenzor
4
它在禁用控件和使用键盘时具有正确的行为。与一般的“状态改变”事件相比,其显著区别在于当复选框被程序更改时,该事件不会触发。 - fadden

15

我把这个放在答案中,因为它太长了,评论容不下:

如果您需要虚拟机在 CheckBox 改变时知道,请将 CheckBox 真正绑定到虚拟机上,而不是一个静态值:

public class ViewModel
{
    private bool _caseSensitive;
    public bool CaseSensitive
    {
        get { return _caseSensitive; }
        set
        {
            _caseSensitive = value;
            NotifyPropertyChange(() => CaseSensitive);

            Settings.Default.bSearchCaseSensitive = value;
        }
    }
}

XAML:

<CheckBox Content="Case Sensitive" IsChecked="{Binding CaseSensitive}"/>

2
@HighScore,谢谢,这是一个解决方案,但对于我的情况来说有些过度了。我不想使用INotifyPropertyChanged,它太繁琐了。 :) - David
4
@David 你是如何处理WPF双向绑定而没有使用 INotifyPropertyChanged 的?此外,这与示例无关,只是因为它是ViewModel属性才存在的。如果你去除它,我的示例也能正常工作。 - Federico Berasategui
1
没错,这是双向绑定。该设置既可读又可写,遗憾的是我没有被通知 setter 的更改。 - David
@RalfdeKleine,我不知道你的评论有什么意义,因为其他人已经指出了。 - David
@RalfdeKleine,我从未说过那样的话。 - David

11

我知道这是一个旧问题,但如果使用MVVM,只需绑定到Command如何?

例如:

<CheckBox Content="Case Sensitive" Command="{Binding bSearchCaseSensitive}"/>

对我来说,它会在 CheckUncheck 两种情况下触发。


2

我发现使用MVVM模式处理已选/未选事件的一种简单而适当的方法是使用Caliburn.Micro,具体如下:

 <CheckBox IsChecked="{Binding IsCheckedBooleanProperty}" Content="{DynamicResource DisplayContent}" cal:Message.Attach="[Event Checked] = [Action CheckBoxClicked()]; [Event Unchecked] = [Action CheckBoxClicked()]" />

在ViewModel中实现一个CheckBoxClicked()方法,以执行您想要的操作。

0

如问题中所述,我不想使用Checked/Unchecked事件处理程序,我关心的是“changed”信号。 - David

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