这些天,我一直在尝试在我的UWP应用程序中实现MVVM模式,作为学习练习,而不使用额外的框架。虽然我仍然很难理解INotifyPropertyChanged接口的实现,所以我目前正在阅读相关内容。我发现有很多不同的方法来实现它,但我无法理解它们之间的区别。
这是csharpcorner建议的链接:
在msdn的this博客文章中,John Shews是这样做的:
这是csharpcorner建议的链接:
public class BaseModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (object.Equals(storage, value)) return false;
storage = value;
this.OnPropertyChaned(propertyName);
return true;
}
private void OnPropertyChaned(string propertyName)
{
var eventHandler = this.PropertyChanged;
if (eventHandler != null)
eventHandler(this, new PropertyChangedEventArgs(propertyName));
}
}
在msdn的this博客文章中,John Shews是这样做的:
public class NotificationBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
// SetField (Name, value); // where there is a data member
protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] String property
= null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
RaisePropertyChanged(property);
return true;
}
// SetField(()=> somewhere.Name = value; somewhere.Name, value)
// Advanced case where you rely on another property
protected bool SetProperty<T>(T currentValue, T newValue, Action DoSet,
[CallerMemberName] String property = null)
{
if (EqualityComparer<T>.Default.Equals(currentValue, newValue)) return false;
DoSet.Invoke();
RaisePropertyChanged(property);
return true;
}
protected void RaisePropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
public class NotificationBase<T> : NotificationBase where T : class, new()
{
protected T This;
public static implicit operator T(NotificationBase<T> thing) { return thing.This; }
public NotificationBase(T thing = null)
{
This = (thing == null) ? new T() : thing;
}
}
这是我在之前的一个SO问题中得到@Tomtom建议的内容:
public abstract class NotifyBase : INotifyPropertyChanged
{
private readonly Dictionary<string, object> mapping;
protected NotifyBase()
{
mapping = new Dictionary<string, object>();
}
protected void Set<T>(T value, [CallerMemberName] string propertyName = "")
{
mapping[propertyName] = value;
OnPropertyChanged(propertyName);
}
protected T Get<T>([CallerMemberName] string propertyName = "")
{
if(mapping.ContainsKey(propertyName))
return (T)mapping[propertyName];
return default(T);
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemeberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if(handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
有人能解释一下这些实现的区别,并告诉我哪个更好吗?特别是:
Tomtom版本中的
Dictionary
有什么用?John版本中的
SetProperty
重载是什么意思?为什么前两个示例没有像最后一个示例那样有
Get
方法?不需要吗?为什么John要添加一个
NotificationBase<T>
类?这是其他人错过的重要事情吗?
提前感谢。
NotificationBase<T>
的目的是什么。它应该被注释掉。看起来字典的用意是让你避免声明私有后备字段,我认为这很愚蠢。我怀疑这两者之所以做出来,是因为有些人只是喜欢为了复杂化而增加不必要的复杂性。使用带有DoSet()的SetProperty重载可以让您传递一个lambda表达式,只有在值发生更改时才会执行该表达式。可能有一些用处。 - 15ee8f99-57ff-4f92-890c-b56153SetProperty
中,以便您不必繁琐地重复以完全相同的方式引发多个属性的OnPropertyChanges
。这看起来完全是可选的,个人认为我不会遵循其中任何一个。 - Wiktor Zychla