I'm a little lost right now. I'm using the CommunityToolkit.Mvvm for MVVM in a small application. My UI consists of some settings and some parameters; I'm updating (performing calculations) once a property changes.
In this case I'd like to fire NotifyPropertyChangedFor
as I do calculations with the focal length of a camera - but this gets never triggered.
So while things are working nicely with 'local' properties I'm having issues with objects that come in via a service (so iot injected) like the focal length.
Simplified example:
I have a data container like this:
public partial class Settings : ObservableObject
{
private CameraSettings cameraSettings;
public CameraSettings CameraSettings
{
get => cameraSettings ?? (cameraSettings = new CameraSettings());
set => SetProperty(ref cameraSettings, value);
}
}
And an object that is actually holding the values:
public partial class CameraSettings: ObservableObject
{
private int focalLength = 15;
public int FocalLength
{
get => focalLength;
set => SetProperty(ref focalLength, value);
}
}
And I have a viewmodel which is supposed to use this:
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(ResultsEditorBox))]
private CameraSettings cameraSettingsContainer;
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(ResultsEditorBox))]
private string connectionType;
public SettingsViewModel(SettingsService settingsService)
{
cameraSettingsContainer = settingsService.Settings.CameraSettings;
}
The ResultEditorBox
is just another local property to update UI
public string ResultsEditorBox
{
get
{
return "UI update done";
}
}
While using any 'local' observed property like connectionType
everything is working as expected and ResultsEditorBox
gets called in the end.
If I do the same with my custom object cameraSettingsContainer
I see that set => SetProperty(ref focalLength, value);
gets called correctly; but the NotifyPropertyChangedFor
doesn't trigger.
To my understanding this should work via the CommunityToolkit.Mvvm.
But why is NotifyPropertyChangedFor
not working via the CameraSettings object?
What you're trying to do here is not possible like that, because child property changes are not automatically propagated up to the highest level.
The [NotifyPropertyChangedFor()]
attribute only applies to the CameraSettingsContainer
property, but not its child properties. You'll need some other way to raise the PropertyChanged
event for ResultsEditorBox
.
One way to solve this would be to subscribe to the PropertyChanged
event of the CameraSettingsContainer
and then raise the notification in the event handler:
public SettingsViewModel(SettingsService settingsService)
{
CameraSettingsContainer = settingsService.Settings.CameraSettings;
CameraSettingsContainer.PropertyChanged += (s,e) =>
{
OnPropertyChanged(nameof(ResultsEditorBox));
}
}
I wrote a blog series about MVVM Source Generators, which you may be interested in. It explains how they work and what happens under the hood.