NotifyPropertyChangedFor 在 ObservableObject 上不起作用

huangapple go评论90阅读模式
英文:

NotifyPropertyChangedFor not working on ObservableObject

问题

我现在有点迷失。我在一个小应用程序中使用CommunityToolkit.Mvvm来进行MVVM开发。我的用户界面包括一些设置和一些参数;当属性更改时,我正在更新(执行计算)。

在这种情况下,我想要在我对相机的焦距进行计算时触发NotifyPropertyChangedFor,但从未触发。

所以,虽然使用“本地”属性的事情进展顺利,但通过服务传入的对象(因此是通过依赖注入的对象)如焦距却存在问题。

简化的示例:

我有一个数据容器,如下所示:

public partial class Settings : ObservableObject
{
    private CameraSettings cameraSettings;

    public CameraSettings CameraSettings
    {
        get => cameraSettings ?? (cameraSettings = new CameraSettings());
        set => SetProperty(ref cameraSettings, value);
    }
}

还有一个实际保存值的对象:

public partial class CameraSettings: ObservableObject
{
    private int focalLength = 15;

    public int FocalLength
    {
        get => focalLength;
        set => SetProperty(ref focalLength, value);
    }
}

我有一个视图模型,应该使用它:

[ObservableProperty]
[NotifyPropertyChangedFor(nameof(ResultsEditorBox))]
private CameraSettings cameraSettingsContainer;

[ObservableProperty]
[NotifyPropertyChangedFor(nameof(ResultsEditorBox))]
private string connectionType;

public SettingsViewModel(SettingsService settingsService)
{
    cameraSettingsContainer = settingsService.Settings.CameraSettings;
}

ResultEditorBox只是另一个本地属性,用于更新用户界面:

public string ResultsEditorBox
{
    get
    {
        return "UI update done";
    }
}

当使用任何“本地”可观察属性,比如connectionType时,一切都按预期工作,并且最终调用了ResultsEditorBox

如果我对我的自定义对象cameraSettingsContainer执行相同操作,我可以看到set => SetProperty(ref focalLength, value);被正确调用;但是NotifyPropertyChangedFor不会触发。

根据我的理解,通过CommunityToolkit.Mvvm应该可以工作。但是为什么NotifyPropertyChangedFor在CameraSettings对象上不起作用呢?

英文:

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?

答案1

得分: 1

你在这里尝试的操作以这种方式是不可能的,因为子属性的更改不会自动传播到最高级别。

[NotifyPropertyChangedFor()] 属性仅适用于 CameraSettingsContainer 属性,而不适用于其子属性。你需要其他方法来触发 ResultsEditorBoxPropertyChanged 事件。

解决方法之一是订阅 CameraSettingsContainerPropertyChanged 事件,然后在事件处理程序中引发通知:

public SettingsViewModel(SettingsService settingsService)
{
    CameraSettingsContainer = settingsService.Settings.CameraSettings;
    CameraSettingsContainer.PropertyChanged += (s,e) =>
    {
        OnPropertyChanged(nameof(ResultsEditorBox));
    }
}

我写了一篇关于 MVVM 源代码生成器的博客系列,你可能会感兴趣。它解释了它们是如何工作的以及底层发生了什么。

英文:

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.

huangapple
  • 本文由 发表于 2023年6月5日 18:31:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76405547.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定