【问题标题】:Confusion about INotifyPropertyChanged and updating Bindings关于 INotifyPropertyChanged 和更新绑定的困惑
【发布时间】:2010-07-07 13:28:18
【问题描述】:

据我(想)了解,在 ModelView 中实现 INotifyPropertyChanged 允许在修改属性的情况下引发 PropertyChanged 事件。

这样,视图应该会收到底层属性已更改的通知,因此 UI 应该获取新的更改。

我的理论是否正确?

我面临的问题是我有一个绑定到 ViewModel 的 Infragistics DataGrid。一旦我更改了日期值,我就可以看到 ViewModel 上的属性是如何正确设置的以及事件是如何引发的。但是我还没有从外部订阅这个事件,UI是如何得到通知的?

我问这个是因为我认为 UI 根本没有通知。我已经放置了第二个文本框,它将 ViewModel 绑定到相同的基础模型属性。但是,如果我使用 DataGrid 修改该属性,则 TextBox (Mode=OneWay) 不会自动更新。

我实际上使用 MVVM-Light Frame 工作并使用 ViewModelBase 而不是 INotifyPropertyChanged 并执行 RaisePropertyChanged(...)。但结果应该是相似的。

我是否必须以某种方式手动为 TextBox 订阅该事件?

编辑:我已经解决了这个问题,但不明白为什么会这样。在回答问题之前,我需要进一步解释一下架构。 Datgrid 绑定到 ViewModelA 中的 propertyA,它返回 ObservableCollection<ViewModelB>. ViewModelB 实际上包含 Grid 应该显示的所有属性。所有这些属性在它们的 Setter 中自然触发 OnProperyChanged。

TextBox 绑定到 PropertyB,它也存在于 ViewModelA 中。但它直接返回一个字符串,所以 PerpertyB 的底层 getter 返回:

_cashflowInputs[0].ProjectedDate.ToString();

但是,如果我不将 TextBox 绑定到这个 propertyB,但也将它绑定到 PropertyA,它就可以工作:

这很奇怪。我期待它以同样的方式工作。两个属性都存在于同一个 ViewModel 上并访问同一个 private ObservableCollection<ViewModelB>,这有什么关系?

public ObservableCollection<ViewModelB> PropertyA
        {
            get { return _cashflowInputs;}
        }

        public string PropertyB
        {
            get { return _cashflowInputs[0].ProjectedDate.ToString(); }
        }

凯夫

【问题讨论】:

  • 只是为了澄清一下,在您的代码示例中 PropertyA 是 ObservableCollection 而 PropertyB 是字符串?您说您将 PropertyA(ObservableCollection)绑定到 TextBox?
  • A DataGrid 绑定到 PropertyA,TextBox 绑定到 PropertyB

标签: .net wpf mvvm mvvm-light


【解决方案1】:

这里快速回顾了当数据对象实现 INotifyPropertyChanged 时数据对象和 UI 元素之间的通知是如何工作的。

1) 调用数据对象的属性设置器来更改属性。

2) 在 setter 中,数据对象更改属性值并引发事件以通知绑定到数据对象的任何 UI 元素属性已更改。引发的事件将包含刚刚更改的属性的名称。

3) UI 元素处理事件并检查事件参数以确定更改了哪个属性。

4) 既然 UI 元素知道哪个属性已更改,它会调用适当的 getter 来获取最新的属性值,并使用该值更新自身。

所以,在你的例子中。如果更新了属性“ProjectedDate”,则会引发一个事件,将属性名称“ProjectedDate”传递给 UI 元素。 UI 元素随后将调用“ProjectedDate”属性的 getter 来刷新自身。

如果从未使用属性名称“PropertyB”作为参数引发事件,则 UI 元素不知道“PropertyB”已更改。因此,如果它绑定到“PropertyB”,它不会用新值刷新自己。在某些时候,必须使用属性名称“PropertyB”引发事件作为 UI 元素的事件参数,以了解它需要使用最新的属性值刷新自身。

【讨论】:

  • 这完美地解释了它。非常感谢您的澄清。现在我明白为什么人们一直把它们称为魔法弦了。 ;)
【解决方案2】:

您是否在文本框上设置了绑定?

<TextBox Text="{Binding Path=PathToMyValue}"/>

【讨论】:

  • 是的,我做到了。 测试是我的 ViewModel 上的一个属性。它正确显示初始值。但是在更新每个 DataGrid 的值时,我希望 TextBox 也能得到更新。但它没有。
  • 我敢打赌,网格不做任何绑定,它只是监视集合以添加/删除项目。我们在使用 Infragistics 数据网格时遇到了问题,因为它在值更改时没有更新,我们需要近乎实时的数据更新。
【解决方案3】:

绑定到 DataGrid 中数据模板内的控件中的 PropertyB 将不起作用,因为控件的数据上下文将是 ViewModelB。如果要将数据模板内的元素绑定到数据模板上下文之外的内容,则需要将其数据上下文设置为其他内容,或者使用元素到元素的数据绑定来绑定到数据模板之外的内容。

【讨论】:

  • 两个控件都在同一个 StackGrid 中,它的 DataContext 绑定到 ViewModelA。此外,我没有使用任何 DataTemplate。 ;) 别担心,答案已经找到了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-05
  • 2012-03-06
  • 2014-06-06
  • 2014-10-30
  • 2011-12-13
  • 2017-12-04
  • 2012-03-06
相关资源
最近更新 更多