According to this answer I should not need to bother about NotifyPropertyChanges Bubbling up the hierachie, still I can't get it to work with a (simplified test-) structure like that:
a Data-Holding Class
public class TestNotifyChanged : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _Test = "default";
public string Test
{
get
{
return _Test;
}
set
{
if(_Test!=value)
{
_Test = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Test"));
}
}
}
}
A ViewModel that used that Test-Class and Test-Property:
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private TestNotifyChanged tnc = new TestNotifyChanged(); // only to init, otherwise VS screams at me
public ViewModel(TestNotifyChanged tnc)
{
tnc = tnc; // getting an instance of TestNotifyChanged from "Master" passed in, which hopefully will be replaces by a singleton class.
}
private string _Test;
public string Test
{
get
{
return tnc.Test; // this might be the crucial part!?
}
set
{
if (_Test != value) // never hits that, as I would expect, but you never know..
{
_Test = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Test")); // of course also never hit, as expected
}
}
}
}
And finally my MainWindow cs
public partial class MainWindow : Window
{
TestNotifyChanged tnc;
public MainWindow()
{
InitializeComponent();
tnc = new TestNotifyChanged();
DataContext = new ViewModel(tnc); // pass in my Test-Object that has the Values.
}
private void ButtonGet_Click(object sender, RoutedEventArgs e)
{
tnc.Test = "new Value";
MessageBox.Show($"{tnc.Test}"); // got "new Value" here!
}
}
And in xaml I have besides that one button a simple TextBlock that is bound to the ViewModel's Test Property:
<TextBlock x:Name="OutputId" Text="{Binding Path=Test, Mode=OneWay}"/>
What is happening now:
The default value "default" is shown in TextBlock.
When I click the button the messageBox shows the "new Value"
TextBlock is not updating to "new Value"
What I want to achieve:
- seems easy: TextBlock should update to "new Value"
I can easily make this work when I directly set the Test Value on the ViewModel - but this doesn't seem right and is far away from what I thought I could structure my app/code. The future goal is to have a Singleton (static won't work I figured out) "RecordStore" that has most of the data (and gets it from an API, from local Database, or just from Memory if any of these are done)
So the question is:
Why is the NotifyPropertyChange not bubbling up to the View/ViewModel?
Or is there another issue I don't see?
I've read INotifyPropertyChanged bubbling in class hierarchy and What is a good way to bubble up INotifyPropertyChanged events through ViewModel properties with MVVM? and https://learn.microsoft.com/en-us/dotnet/framework/winforms/how-to-implement-the-inotifypropertychanged-interface and OnPropertyChange called but not taking any effect on UI
most of those questions are also quite old...
EDIT:
I tried @MineR 's suggestion that way:
// made tnc public in ViewModel
public TestNotifyChanged tnc = new TestNotifyChanged();
// changed Binding directly to that (and it's Property):
<TextBlock x:Name="OutputId" Text="{Binding Path=tnc.Test, Mode=OneWay}"/>
Unfortunately now I don't even get the default, so I must have misunderstood smth.
EDIT2:
I did one thing wrong in the 1st edit:
// this isn't recognized as bindable parameter:
public TestNotifyChanged tnc = new TestNotifyChanged();
// it instead has to be
public TestNotifyChanged tnc { get; }
And I made it TNC
, removed the local Test
parameter, bound directly to Path=TNC.Test
So I understood, that PropertyChanges do not bubble up the way I hoped/thought, it's better to bind directly down to the nested object.