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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18228654/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 11:34:40  来源:igfitidea点击:

WPF binding update notification for nested property when parent property changes

c#wpfmvvmbinding

提问by Felix C

I have a ViewModel with a complex property type and want to bind my view to a nested property of this object.

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

My ViewModel is implementing INotifyPropertyChanged(or do be extact BaseViewModelis implementing it). The class of the parent property is not implementing INotifyPropertyChanged.

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

The class Car is not implementing INotifyPropertyChanged. But I'm not changing the property Manufacturer, I change the MyCarPropertyproperty, and so I expect that the OnNotifyPropertyChangedevent will trigger the value update?

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

When I'm updating the value of the parent property, the nested property is not updating. Can you tell me how can I implement this functionality?

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

ViewModel

视图模型

public class ViewModel : BaseViewModel
{
    private Car _myCarProperty;

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

            _myCarProperty = value;
            OnPropertyChanged();
        }
    }
}

Binding in the View

在视图中绑定

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

When I change the value of MyCarPropertythe View does not update.

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

Thanks for any help!

谢谢你的帮助!

Edit: OnPropertyChanged() implementation

编辑: 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

采纳答案by Greg D

"The class Car is not implementing INotifyPropertyChanged. But I'm not changing the property Manufacturer, I change the MyCarProperty property, and so I expect that the OnNotifyPropertyChanged event will trigger the value update?"

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

Nope, it won't trigger the value update a level down. Bindings don't listen to property changes for an entire path, they listen only to the object that they're bound to.

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

I see a couple options off the top of my head (in order of my preference when I run into this):

我在脑海中看到了几个选项(按照我遇到这个的偏好顺序):

  1. Bind to the car, not the sub property, and create a data templatethat displays what you want out of it.
  2. Manually kick the binding by calling UpdateTarget on it's BindingExpressionwhen you need to.
  1. 绑定到汽车,而不是子属性,并创建一个数据模板来显示您想要的内容。
  2. BindingExpression在需要时通过调用 UpdateTarget 手动启动绑定。

I know it looks like there's a lot more to learn on the data template route, but I promise you that data templates will prove vastlymore powerful, scalable, maintainable, and useful than manually kicking bindings as you work more in WPF. (Also, once you understand them, I think they're actually lesswork than manually kicking bindings).

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

Good luck!

祝你好运!

回答by Jeroen van Langen

I'm not an WPF expert, but I think it's because you've chosen the wrong path.

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

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

update:

更新:

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

回答by notracs

The accepted answer explains how to handle the case where a sub-propertyon a Binding Source is changed and you wish to update the view - which is not what the question is asking. WPF will in fact respond to changes from many levels down, so long as you are notifying changes for any properties being changed within the specified path.

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

As for this:

至于这个:

"The class Car is not implementing INotifyPropertyChanged. But I'm not changing the property Manufacturer, I change the MyCarProperty property, and so I expect that the OnNotifyPropertyChanged event will trigger the value update?"

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

WPF handles this already.

WPF 已经处理了这个问题。

In your example, ViewModelis the Binding Source. When you set MyCarProperty(firing the NotifyPropertyChangedevent), WPF will re-evaluate the Binding Target Value using the Binding Path for the newBinding Source object - updating your view with the new Manufacturer.

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

I have tested this with a simple WPF app - it also holds true for very deeply nested Paths:

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

https://pastebin.com/K2Ct4F0F

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}" />