ViewModel 类应该实现 INotifyPropertyChanged 还是我可以使用对象组合

本文关键字:可以使 我可以 对象 组合 实现 INotifyPropertyChanged ViewModel | 更新日期: 2023-09-27 18:36:56

我正在开发一个带有C#和.NET Framework 4.6的MVVM WPF应用程序。

我有这个类:

public class ObservableObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChangedEvent(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

我在这里实现了INotifyPropertyChanged因为我不想在所有的 ViewModel 类中实现它。

要使用此类,我使用继承:

public class Presenter : ObservableObject
{
    private string _someText;
    public string SomeText
    {
        get { return _someText; }
        set
        {
            _someText = value;
            RaisePropertyChangedEvent("SomeText");
        }
    }
}

但是,有没有办法使用对象组合ObservableObject

我将对象组合理解为在类 Presenter 中创建 ObservableObject 的私有对象实例,而不是继承。

我不确定是否有任何视图模型类应该实现INotifyPropertyChanged.

更新:
这不是一个重复的问题。我问的是ViewModel是否总是必须实现INotifyPropertyChanged接口,或者相反,我可以使用对象组合。我之前已经解释过了。请仔细阅读我的问题。

ViewModel 类应该实现 INotifyPropertyChanged 还是我可以使用对象组合

嗯,...ViewModels 最好被视为组合,但通知部分应该是接口的实现(或者在您的情况下是继承)。您有您的 DTO,您的 ViewModels 将是 DTO 的组合,具体取决于场景。

相同内容的实现可能很乏味,但对于 WPF 来说仍然是必要的。为了简化流程,你可以做的是使用像Fody这样的Veawrs。它会更改您对视图模型的观察。默认情况下,VM 的所有属性都是可观察属性,但可以排除不需要的属性,也可以为一个属性定义,让 UI 知道它也应更新其他属性。

它使代码非常干净和简单。你不需要实现接口,但如果你为类提供所需的属性,它将在构建时继承。

如果要通过避免代码重复和在代码中使用字符串来提高健壮性。然后,您可以使用以下基类。

我不知道作曲的方法,但这是我所知道的最好的方法。因为它有一些额外的好处(克隆变得容易a.s.o.)

public abstract class BindingBase : INotifyPropertyChanged
{
    private IDictionary<string, object> _backingFields;
    private IDictionary<string, object> BackingFields
    {
        get { return _backingFields ?? (_backingFields = new Dictionary<string, object>(); }
    }    
protected T GetValue<T>(Expression<Func<T>gt; expr) { var name = GetName(expr); return BackingFields.Contains(name) ? (T)BackingFields[name].Value : default(T); }
protected void SetValue<T>(Expression<Func<T>gt; expr, T value) { var name = GetName(expr); if (BackingFields.Contains(name) && BackingFields[name].Value.Equals(value)) return; // return without doing anything, since the value is not changing
BackingFields[name] = value; RaisePropertyChanged(name); }
private void RaisePropertyChanged(string name) { // you know this part
}
private string GetName (Expression<Func<T> expr) { // implementation can be found via google } }
使用非常简单。
public class BindingChild : BindingBase
{
    public string SampleProperty
    {
        get { return GetValue(() => SampleProperty); }
        set { SetValue(() => SampleProperty, value); }
    }
}

相关文章: