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
接口,或者相反,我可以使用对象组合。我之前已经解释过了。请仔细阅读我的问题。
嗯,...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); }
}
}