Updating a bound object with INotifyPropertyChanged does not work
Hi,
I'm having trouble when updating the UI that is bound to an scriptable object.
I simplified my example extremely, so it can be understood easier. I hope that I managed to catch the essence of it.
I have a UserControl called "MilestoneViewComponent". It expects an object of my PlayerData (ScriptableObject) class and displays some of its attribtues.
This UserControl is being used in the Main View, where I have a binding to my PlayerData.
My Observation:
I have a script that holds my PlayerDataObject and implements INotifyPropertyChanged.
When I call INotifyPropertyChanged on "PlayerData" my view does not update.
I added a float variable called "Money".
When I call INotifyPropertyChanged on "Money" my view does update.
Question:
Is it possible that you can't pass objects as a binding and still call updates on them when only data inside the object has changed?
Here is my Main View xaml:
This is my code behind of the MilestoneViewComponent:
I hope that I did not simplify my issue too much. I'm happy to add some more information if needed.
Thanks in advance,
David
I'm having trouble when updating the UI that is bound to an scriptable object.
I simplified my example extremely, so it can be understood easier. I hope that I managed to catch the essence of it.
I have a UserControl called "MilestoneViewComponent". It expects an object of my PlayerData (ScriptableObject) class and displays some of its attribtues.
This UserControl is being used in the Main View, where I have a binding to my PlayerData.
My Observation:
I have a script that holds my PlayerDataObject and implements INotifyPropertyChanged.
When I call INotifyPropertyChanged on "PlayerData" my view does not update.
I added a float variable called "Money".
When I call INotifyPropertyChanged on "Money" my view does update.
Question:
Is it possible that you can't pass objects as a binding and still call updates on them when only data inside the object has changed?
Here is my Main View xaml:
Code: Select all
<UserControl x:Class="Testing.GameView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
...
Focusable="True"
x:Name="Root">
<Grid x:Name="RootGrid">
<local:MilestoneViewComponent PlayerData="{Binding PlayerData, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Money="{Binding CurrentMoney, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</UserControl>
Code: Select all
public partial class MilestoneViewComponent : UserControl, INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
public PlayerDataSO PlayerData {
get { return (PlayerDataSO) GetValue(PlayerDataProperty); }
set { SetValue(PlayerDataProperty, value); }
}
public static void OnPlayerDataChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) {
MilestoneViewComponent milestoneViewComponent = sender as MilestoneViewComponent;
//Here some of my other bindings are updated that are read from the player
milestoneViewComponent.OnPropertyChanged(nameof(PlayerName));
/*
This is not getting called when I update the PlayerData
*/
}
public static readonly DependencyProperty PlayerDataProperty = DependencyProperty.Register(
nameof(PlayerData), typeof(PlayerDataSO), typeof(MilestoneViewComponent), new PropertyMetadata(null, new PropertyChangedCallback(OnPlayerDataChanged)));
public Float Money {
get { return (Float) GetValue(MoneyProperty); }
set { SetValue(MoneyProperty, value); }
}
public static void OnMoneyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) {
MilestoneViewComponent milestoneViewComponent = sender as MilestoneViewComponent;
//Here some of my other bindings are updated that are read from the player
milestoneViewComponent.OnPropertyChanged(nameof(PlayerName));
/*
This is getting called when I update Money
*/
}
public static readonly DependencyProperty MoneyProperty = DependencyProperty.Register(
nameof(Money), typeof(Float), typeof(MilestoneViewComponent), new PropertyMetadata((Float) 0, new PropertyChangedCallback(OnMoneyChanged)));
}
Thanks in advance,
David
-
-
sfernandez
Site Admin
- Posts: 2908
- Joined:
Re: Updating a bound object with INotifyPropertyChanged does not work
Hi,
I want to mention that you don't need to implement the INotifyPropertyChanged for the UserControl if you are using DependencyProperties, as the change notification is built-in for them. So whenever the value of the DependencyProperty changes, it will call the PropertyChangedCallback and also update any bindings to that property.
You want to implement INotifyPropertyChanged for classes that expose simple CLR properties (for example in the view models).
Regarding your question, you should be able to bind to an object, and then have bindings to that object inside the user control, something like
But when you call PropertyChanged on "PlayerData", have you set a new instance of that class in the PlayerData property, or is it just the properties inside PlayerData that have changed?
Because the dependency property will realize that the PlayerData instance is the same and won't notify of any change to the bindings inside the user control.
Is that what is happening in your case?
I want to mention that you don't need to implement the INotifyPropertyChanged for the UserControl if you are using DependencyProperties, as the change notification is built-in for them. So whenever the value of the DependencyProperty changes, it will call the PropertyChangedCallback and also update any bindings to that property.
You want to implement INotifyPropertyChanged for classes that expose simple CLR properties (for example in the view models).
Regarding your question, you should be able to bind to an object, and then have bindings to that object inside the user control, something like
Code: Select all
<TextBlock Text="{Binding PlayerData.Name, ElementName=MilestoneView}"/>
Because the dependency property will realize that the PlayerData instance is the same and won't notify of any change to the bindings inside the user control.
Is that what is happening in your case?
Re: Updating a bound object with INotifyPropertyChanged does not work
Hi,
thanks for the quick reply.
I know that I can bind properties like this as well.
In my case I don't want to do this as I would need to create about 30 Dependency properties if I want to do it this way. That's a bit too many for my liking.
The INotifyChangedProperty inside the UserControl is there, because I have some attributes bound that are not Dependency Properties.
Here is some pseudocode that explains what I'm doing:
And yes, my PlayerData object instance does not change. Only the values inside.
I was hoping to "force" an update by notifying the PlayerData change manually, even though the instance is the same.
Is there a way to achieve this in a way, so I don't have to implement a "dummy" depency property?
Could an array be the solution or would it have the same problem as an object, if the array instance does not change?
Thanks,
David
thanks for the quick reply.
I know that I can bind properties like this as well.
Code: Select all
<TextBlock Text="{Binding PlayerData.Name, ElementName=MilestoneView}"/>
The INotifyChangedProperty inside the UserControl is there, because I have some attributes bound that are not Dependency Properties.
Here is some pseudocode that explains what I'm doing:
Code: Select all
public PlayerData PlayerData1; //dependency property
public PlayerData PlayerData2; //dependency property
//I'm calling a INotifyPropertyChanged within the UserControl to signal an update on this attribute
//when PlayerData inside my dependency properties have changed.
//This bool would be the value that actually get's displayed inside my UserControl
public bool HaveSameName {
get { return PlayerData1.Name == PlayerData2.Name; }
}
And yes, my PlayerData object instance does not change. Only the values inside.
I was hoping to "force" an update by notifying the PlayerData change manually, even though the instance is the same.
Is there a way to achieve this in a way, so I don't have to implement a "dummy" depency property?
Could an array be the solution or would it have the same problem as an object, if the array instance does not change?
Thanks,
David
-
-
sfernandez
Site Admin
- Posts: 2908
- Joined:
Re: Updating a bound object with INotifyPropertyChanged does not work
In my example the Name property was not intended to be a DependencyProperty, just a CLR property of the PlayerData instance. But if those properties could change, it will require that PlayerData class implements the INotifyPropertyChanged interface and properly notify when a property value changes.In my case I don't want to do this as I would need to create about 30 Dependency properties if I want to do it this way. That's a bit too many for my liking.
Ok, that makes sense then.The INotifyChangedProperty inside the UserControl is there, because I have some attributes bound that are not Dependency Properties.
If you want to force an update when the instance does not change, you can temporaly set the value to null and set it again, but this is a hack.And yes, my PlayerData object instance does not change. Only the values inside.
I was hoping to "force" an update by notifying the PlayerData change manually, even though the instance is the same.
Is there a way to achieve this in a way, so I don't have to implement a "dummy" depency property?
Exposing a Changed event in your PlayerData class would be better, so the user control can hook to that to detect changes inside the instance (in case you don't want to implement the INotifyPropertyChanged interface in that class).
This will have the same problem if the item instance does not change.Could an array be the solution or would it have the same problem as an object, if the array instance does not change?
Re: Updating a bound object with INotifyPropertyChanged does not work
Ok,
thank you. In this case I will need to rework my UserControl.
At least I know why it's not working now :D
thank you. In this case I will need to rework my UserControl.
At least I know why it's not working now :D
-
-
sfernandez
Site Admin
- Posts: 2908
- Joined:
Re: Updating a bound object with INotifyPropertyChanged does not work
Please let us know if you find any issues.
Glad to help.
Glad to help.
Who is online
Users browsing this forum: No registered users and 0 guests