【问题标题】:Databinding with INotifyPropertyChanged instead of DependencyProperties使用 INotifyPropertyChanged 而不是 DependencyProperties 进行数据绑定
【发布时间】:2009-12-29 19:48:04
【问题描述】:

一周多来,我一直在努力让数据绑定在 WPF 中工作。我确实在这里获得了有关 DataContext 的宝贵帮助,并且我确实通过 DependencyProperties 使数据绑定工作。在我学习数据绑定的过程中,我遇到了很多关于 INotifyPropertyChanged 以及它在很多方面比 DP 更好的讨论。我想我会试一试。

我正在使用 Josh Smith 的基本 ViewModel 类,而我的 ViewModel 是从它派生的。但是,我在让数据绑定工作时遇到了一些麻烦,希望这里有人能告诉我哪里出错了。

在我的 ViewModel 类中,我有一个 ObservableCollection<string>。在我的 GUI 中,我有一个绑定到此 OC 的组合框,即

<ComboBox ItemsSource="{Binding PluginNames}" />

GUI 的 DataContext 设置为 ViewModel,即

private ViewModel _vm;

public GUI()
{
  InitializeComponent();
  _vm = new ViewModel();
  this.DataContext = _vm;
}

并且 ViewModel 具有名为“PluginNames”的 OC:

public class ViewModel
{
  public ObservableCollection<string> PluginNames;  // this gets instantiated and added to elsewhere
}

加载 GUI 时,会调用一个方法来实例化 OC 并向其添加插件名称。 OC修改后,我调用RaisePropertyChanged( "PluginNames")。我期待,因为 WPF 数据绑定模型认识到 INotifyPropertyChanged,这就是我需要做的所有事情,它会“神奇地工作”并使用加载的插件更新组合框项目......但它没有。

有人可以指出我在这里做错了什么吗?谢谢!

更新:我不知道为什么,但现在不是没有进行任何明显的更新,而是根本没有找到该属性。我认为我真的很愚蠢,并且在某个地方错过了重要的一步。

【问题讨论】:

    标签: wpf mvvm inotifypropertychanged dependency-properties


    【解决方案1】:

    当您使用 INotifyPropertyChanged 时,有两件事:

    1. 您需要使用属性,而不是字段
    2. 您应该在设置 hte 属性时始终引发属性更改事件。

    您需要重新设计它,使其看起来更像:

    private ObservableCollection<string> pluginNames;
    public ObservableCollection<string> PluginNames
    {
        get { return pluginNames; }
        set {
            this.pluginNames = value;
            RaisePropertyChanged("PluginNames"); // This should raise the PropertyChanged event - use whatever your VM class does for this
        }
    }
    

    这应该会导致一切重新填充。

    【讨论】:

    • 事实上,可能没有理由在属性上设置 setter,因为它是一个集合(并且是一个可观察的集合)。
    • 是的 - 但他故意提到他是在运行时设置的,所以我把它包括在内。
    • Reed,我喜欢你展示的方式......我绝对应该公开 setter 并在那里调用 RaisePropertyChanged,就像我今天看到的所有其他示例一样。完美!
    • @D. Matsumoto:这是使用 INotifyPropertyChanged 时处理属性的标准方法。根据您使用的 ViewModel 基类,确切的语法可能会有所变化(RaisePropertyChanged 可以通过不同的方式完成),但您需要遵循这个通用模式。此外,如果新值与原始值不同,通常只提高属性更改...
    • 太棒了,听起来不错。一旦我对此感到更加熟悉,我将尝试使用“无字符串”方式来处理属性名称——我认为如果符号不匹配,人们会使用表达式树来获取编译器错误。
    【解决方案2】:

    您似乎公开了字段而不是属性。绑定仅适用于属性...将其更改为:

    public class ViewModel
    {
      public ObservableCollection<string> PluginNames {get; private set;} 
    }
    

    【讨论】:

    • 不要使用自动属性 ​​- 它们不会引发 PropertyChanged 事件。
    • 绝对正确。啊!我最终会在这方面做得更好。 :)
    • 这里有正确的礼仪来接受最古老的正确答案吗?我想是的。
    • 您可以为ObservableCollection&lt;T&gt; 使用自动属性。不过,setter 应该是私有的。
    • sixlettervariables:这是真的如果你永远不会实例化一个新的集合——但在这种情况下你应该使用readonly字段和只读属性。跨度>
    猜你喜欢
    • 2010-12-14
    • 1970-01-01
    • 1970-01-01
    • 2011-07-04
    • 1970-01-01
    • 2021-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多