I have a ViewModel with a complex property type and want to bind my view to a nested property of this object.
My ViewModel is implementing INotifyPropertyChanged
(or do be extact BaseViewModel
is implementing it). The class of the parent property is not implementing INotifyPropertyChanged
.
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?
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 MyCarProperty
the View does not update.
Thanks for any help!
Edit: OnPropertyChanged() implementation
#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
Set the NotifyOnTargetUpdated or NotifyOnSourceUpdated property (or both) to true in the binding. The handler you provide to listen for this event must be attached directly to the element where you want to be informed of changes, or to the overall data context if you want to be aware that anything in the context has changed.
Here is an example that shows how to set up for notification when a target property has been updated. You can then assign a handler based on the EventHandler<T> delegate, OnTargetUpdated in this example, to handle the event:
"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?" Nope, it won't trigger the value update a level down.
Windows Presentation Foundation (WPF) raises a data update event each time that the binding source or target has been updated. Internally, this event is used to inform the user interface (UI) that it should update, because the bound data has changed. Note that for these events to work, and also for one-way or two-way binding to work properly, ...
"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?"
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):
BindingExpression
when you need to.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 vastly more 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 less work than manually kicking bindings).
Good luck!
The accepted answer explains how to handle the case where a sub-property on 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.
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?"
WPF handles this already.
In your example, ViewModel
is the Binding Source. When you set MyCarProperty
(firing the NotifyPropertyChanged
event), WPF will re-evaluate the Binding Target Value using the Binding Path for the new Binding Source object - updating your view with the new Manufacturer
.
I have tested this with a simple WPF app - it also holds true for very deeply nested Paths:
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}" />
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With