【问题标题】:WPF CheckBox's IsChecked property doesn't match binding source's valueWPF CheckBox 的 IsChecked 属性与绑定源的值不匹配
【发布时间】:2011-01-25 03:55:25
【问题描述】:

在我的 WPF 应用程序中,我有一个 CheckBox,其 IsChecked 值绑定到我的视图模型中的一个属性。请注意,我已经注释掉了在我的视图模型中设置值的实际行。这是标准模式:

View.xaml

<CheckBox IsChecked="{Binding Path=SomeProperty}" />

ViewModel.cs

public bool SomeProperty
{
    get { return this.mSomeProperty; }
    set
    {
        if (value != this.mSomeProperty)
        {
            //this.mSomeProperty = value;
            NotifyPropertyChanged(new PropertyChangedEventArgs("SomeProperty"));
        }
    }
}

当我单击CheckBox 时,我预计不会发生任何事情,因为this.mSomeProperty 的值没有设置。然而,观察到的行为是 CheckBox 被选中和取消选中,无论 this.mSomeProperty 的值如何。

发生了什么事?为什么我的绑定不强制 CheckBox 显示底层数据模型的设置?

【问题讨论】:

    标签: wpf binding checkbox ischecked


    【解决方案1】:

    因为 WPF 在更新源后不会自动从绑定源重新加载。这可能部分是出于性能原因,但主要是为了处理绑定失败。例如,考虑绑定到整数属性的 TextBox。假设用户键入 123A。 WPF 希望继续显示用户键入的内容以便他们可以更正它,而不是突然将 TextBox 内容重置为属性的旧值。

    所以当你单击 CheckBox 时,WPF 假定它应该继续显示 控件 状态,而不是重新检查绑定的属性。

    我发现的唯一方法(不是很优雅)是在 WPF 从调用属性设置器返回后 引发 PropertyChanged。这可以使用 Dispatcher.BeginInvoke 来完成:

    set
    {
      // ...actual real setter logic...
      Action notify = () => NotifyPropertyChanged(...);
      Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, notify);
    }
    

    通过将其合并到 NotifyPropertyChanged 实现中,这可能会变得不那么可怕,这样您就不必因为这个实现问题而污染各个属性。您也许还可以使用 NotifyOnSourceUpdated 和 SourceUpdated 附加事件,但我还没有探索过这种可能性。

    【讨论】:

    • 当然是一个创造性的解决方案,但是......呃......我希望那里有一个更清洁的解决方案!
    • Microsoft 更改了 .NET 4.0 中的绑定行为,因此控件现在将在设置绑定属性后对其进行检查。 karlshifflett.wordpress.com/2009/05/27/…
    • itowlson 的出色回答和 emddudley 的良好反馈。我可以确认此行为仅发生在 .NET 3.5 中 - 它似乎已在 .NET 4 的 WPF 中得到修复。
    猜你喜欢
    • 2016-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-24
    • 1970-01-01
    • 2016-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多