父属性更改时嵌套属性的 WPF 绑定更新通知

Posted

技术标签:

【中文标题】父属性更改时嵌套属性的 WPF 绑定更新通知【英文标题】:WPF binding update notification for nested property when parent property changes 【发布时间】:2013-08-16 05:22:23 【问题描述】:

我有一个具有复杂属性类型的 ViewModel,并希望将我的视图绑定到该对象的嵌套属性。

我的 ViewModel 正在实现 INotifyPropertyChanged(或者确切地说,BaseViewModel 正在实现它)。父属性的类没有实现INotifyPropertyChanged

类 Car 没有实现 INotifyPropertyChanged。但是我没有更改Manufacturer属性,我更改了MyCarProperty属性,所以我希望OnNotifyPropertyChanged事件会触发值更新?

当我更新父属性的值时,嵌套属性没有更新。你能告诉我如何实现这个功能吗?

视图模型

public class ViewModel : BaseViewModel

    private Car _myCarProperty;

    public Car MyCarProperty
    
        get  return _myCarProperty; 
        set
        
            if (value == _myCarProperty) return;

            _myCarProperty = value;
            OnPropertyChanged();
        
    

在视图中绑定

<TextBlock Text="Binding Path=MyCarProperty.Manufacturer" />

当我更改 MyCarProperty 的值时,视图不会更新。

感谢您的帮助!

编辑:OnPropertyChanged() 实现

#region INotifyPropertyChanged

public event PropertyChangedEventHandler PropertyChanged;

[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)

    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
    
        handler(this, new PropertyChangedEventArgs(propertyName));
    


#endregion INotifyPropertyChanged

【问题讨论】:

您通知子属性了吗? Car 没有实现INotifyPropertyChanged。但是我没有更改属性Manufacturer,我更改了MyCarProperty 属性,所以我希望OnNotifyPropertyChanged 事件会触发值更新? - 请查看我编辑的问题。 您能告诉我们 OnPropertyChanged 是如何实现的吗? 我添加了 OnPropertyChanged 实现。 @FelixC 是你的BaseViewModel 告诉编译器它正在实现 INotifyPropertyChanged,例如public class BasseViewModel: INotifyPropertyChanged?当我做了一个小模型时,你的例子似乎奏效了。 【参考方案1】:

“类 Car 没有实现 INotifyPropertyChanged。但我没有 更改属性制造商,我更改 MyCarProperty 属性,所以我希望 OnNotifyPropertyChanged 事件将 触发值更新?”

不,它不会触发向下一级的值更新。绑定不会监听整个路径的属性更改,它们只监听绑定到的对象。

我想到了几个选项(当我遇到这个时,按照我的偏好排序):

    绑定到汽车,而不是子属性,并创建一个 data template 来显示您想要的内容。 需要时,通过在其 BindingExpression 上调用 UpdateTarget 手动解除绑定。

我知道在数据模板路线上看起来还有很多东西要学,但我向你保证,数据模板将证明非常比手动启动绑定更强大、可扩展、可维护和有用当您在 WPF 中工作更多时。 (另外,一旦你理解了它们,我认为它们实际上比手动踢绑定的工作要少

祝你好运!

【讨论】:

谢谢格雷格!我知道数据模板,应该没有任何问题。前段时间我遇到了同样的问题,我记得我过去发现了一些听起来像“看起来很深的绑定”的东西,但我想这只是我找到的VeryObservableCollection here - 这对解决这个问题没有帮助.我希望存在类似的东西。但是数据模板的想法是完美的:) 对不起,什么? WPF 不听路径上的变化?我希望在开始到处使用链式路径之前就知道这一点。嘿,停下。有用! ;) @Greg D,“数据模板”链接已过时。对不起,我只是觉得无聊。 确实无聊!更新了我认为是原始链接的内容。 :)【参考方案2】:

接受的答案解释了如何处理绑定源上的 子属性 更改并且您希望更新视图的情况 - 这不是问题所要问的。 WPF 实际上会响应来自多个级别的更改,只要您通知更改指定路径内的任何属性即可。

至于这个:

“Car 类没有实现 INotifyPropertyChanged。但我没有更改属性 Manufacturer,我更改了 MyCarProperty 属性,所以我希望 OnNotifyPropertyChanged 事件会触发值更新?”

WPF 已经处理了这个问题。

在您的示例中,ViewModel 是绑定源。当您设置 MyCarProperty(触发 NotifyPropertyChanged 事件)时,WPF 将使用 new 绑定源对象的绑定路径重新评估绑定目标值 - 使用新的 @987654325 更新您的视图@。

我已经用一个简单的 WPF 应用程序对此进行了测试 - 它也适用于嵌套非常深的路径:

https://pastebin.com/K2Ct4F0F

<!-- When MyViewModel notifies that "MyCarProperty" has changed, -->
<!-- this binding updates the view by traversing the given Path -->
<TextBlock Text="Binding Path=MyCarProperty.Model.SuperNested[any][thing][you][want][to][try][and][access].Name" />

【讨论】:

【参考方案3】:

我不是 WPF 专家,但我认为这是因为您选择了错误的路径。

<TextBlock Text="Binding Path=MyCarProperty, Value=Manufacturer" />

更新:

<TextBlock Text="Binding Source=MyCarProperty, Path=Manufacturer" />

【讨论】:

根据this没有value属性。 顺便说一句:绑定正在工作,只是不传播值更新。

以上是关于父属性更改时嵌套属性的 WPF 绑定更新通知的主要内容,如果未能解决你的问题,请参考以下文章

模型更改时刷新 ViewModel 的所有属性的数据绑定的好方法

WPF学习第二十九章 元素绑定——将元素绑定到一起

数据绑定如何避免 WPF 中的递归更新?

当 MVVM 中的属性更改时通知可观察集合

属性更改通知(INotifyPropertyChanged)——针对ObservableCollection

WPF DataGridCheckBoxColumn 绑定值后不能选中以及 能选中后,不能进行属性通知