DavidG
Topic Author
Posts: 11
Joined: 06 Dec 2022, 12:14

Updating a bound object with INotifyPropertyChanged does not work

06 Sep 2023, 12:24

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:
<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>
This is my code behind of the MilestoneViewComponent:
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)));
     		
}	
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
 
User avatar
sfernandez
Site Admin
Posts: 3013
Joined: 22 Dec 2011, 19:20

Re: Updating a bound object with INotifyPropertyChanged does not work

06 Sep 2023, 12:59

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
<TextBlock Text="{Binding PlayerData.Name, ElementName=MilestoneView}"/>
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?
 
DavidG
Topic Author
Posts: 11
Joined: 06 Dec 2022, 12:14

Re: Updating a bound object with INotifyPropertyChanged does not work

06 Sep 2023, 13:29

Hi,
thanks for the quick reply.

I know that I can bind properties like this as well.
<TextBlock Text="{Binding PlayerData.Name, ElementName=MilestoneView}"/>
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:
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
 
User avatar
sfernandez
Site Admin
Posts: 3013
Joined: 22 Dec 2011, 19:20

Re: Updating a bound object with INotifyPropertyChanged does not work

06 Sep 2023, 20:39

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.
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.
The INotifyChangedProperty inside the UserControl is there, because I have some attributes bound that are not Dependency Properties.
Ok, that makes sense then.
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?
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.
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).
Could an array be the solution or would it have the same problem as an object, if the array instance does not change?
This will have the same problem if the item instance does not change.
 
DavidG
Topic Author
Posts: 11
Joined: 06 Dec 2022, 12:14

Re: Updating a bound object with INotifyPropertyChanged does not work

07 Sep 2023, 20:21

Ok,
thank you. In this case I will need to rework my UserControl.
At least I know why it's not working now :D
 
User avatar
sfernandez
Site Admin
Posts: 3013
Joined: 22 Dec 2011, 19:20

Re: Updating a bound object with INotifyPropertyChanged does not work

13 Sep 2023, 20:05

Please let us know if you find any issues.
Glad to help.
 
decai
Posts: 54
Joined: 06 Jul 2016, 18:19

Re: Updating a bound object with INotifyPropertyChanged does not work

15 Sep 2023, 16:13

deleted

Who is online

Users browsing this forum: No registered users and 1 guest