ViewModel类应该实现INotifyPropertyChanged还是可以使用Object组合?

时间:2016-03-01 12:12:14

标签: c# wpf inheritance mvvm composition

我正在使用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类中实现它。

要使用此类,我使用inherit:

public class Presenter : ObservableObject
{
    private string _someText;

    public string SomeText
    {
        get { return _someText; }
        set
        {
            _someText = value;
            RaisePropertyChangedEvent("SomeText");
        }
    }
}

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

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

我不确定是否有任何ViewModel类应该实现INotifyPropertyChanged

更新
这不是重复的问题。我问的是ViewModel是否总是要实现INotifyPropertyChanged接口,或者我可以使用Object组合。我以前解释过。请仔细阅读我的问题。

2 个答案:

答案 0 :(得分:0)

嗯,... ViewModels最好被视为Composition,但通知部分应该是Interface的实现(或者在你的case继承中)。您拥有DTO,ViewModel将是DTO的组合,具体取决于方案。

同样的东西的这种实现可能是乏味的,但对于WPF仍然是必要的。您可以采取哪些措施来简化流程,即使用像Fody这样的Veawrs。它会改变您对ViewModel的观察。 VM的所有属性都是默认的可观察属性,但是您可以排除那些您不想要的属性,或者您可以定义一个属性以让UI知道它还应该更新其他属性。

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

答案 1 :(得分:0)

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

我不知道合成的方法,但这个是我所知道的最好的方法。因为它有一些额外的好处(克隆变得容易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); }
    }
}