如果您严格遵循 MVVM 的概念,那么您对连接值与模型的属性的实现是不正确的。
此实现假定 ViewModel 了解模型的内部结构和功能。
而 ViewModel 不应该有这样的知识。
在 MVVM 的“严格”实现中,模型没有属性。
她只有方法和事件。
ViewModel 调用公共方法并将所需的值传递给它。
之后模型的状态是否会改变 - ViewModel 不知道。
如果状态发生了变化,那么模型会引发一个事件。
收到此事件后,ViewModel 会读取必要的数据并更新其属性,这些属性用于在 View 中进行绑定。
演示代码:
型号
public delegate void NameChangedHandler(object sender, string newName);
public class ModelName
{
public event NameChangedHandler NameChangedEvent;
private string name;
public void SendName(string name)
{
// Some business logic to handle the accepted value.
// You can transfer to the server, change other values and the like.
// In this example is simply stored in a private field.
name = name.Trim();
if (this.name != name)
{
this.name = name;
NameChangedEvent?.Invoke(this, this.name);
}
}
}
INPC的基本实现
/// <summary>Base class implementing INotifyPropertyChanged.</summary>
public abstract class BaseINPC : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>Called AFTER the property value changes.</summary>
/// <param name="propertyName">The name of the property.
/// In the property setter, the parameter is not specified. </param>
public void RaisePropertyChanged([CallerMemberName] string propertyName = "")
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
/// <summary> A virtual method that defines changes in the value field of a property value. </summary>
/// <typeparam name = "T"> Type of property value. </typeparam>
/// <param name = "oldValue"> Reference to the field with the old value. </param>
/// <param name = "newValue"> New value. </param>
/// <param name = "propertyName"> The name of the property. If <see cref = "string.IsNullOrWhiteSpace (string)" />,
/// then ArgumentNullException. </param>
/// <remarks> If the base method is not called in the derived class,
/// then the value will not change.</remarks>
protected virtual void Set<T>(ref T oldValue, T newValue, [CallerMemberName] string propertyName = "")
{
if (string.IsNullOrWhiteSpace(propertyName))
throw new ArgumentNullException(nameof(propertyName));
if ((oldValue == null && newValue != null) || (oldValue != null && !oldValue.Equals(newValue)))
OnValueChange(ref oldValue, newValue, propertyName);
}
/// <summary> A virtual method that changes the value of a property. </summary>
/// <typeparam name = "T"> Type of property value. </typeparam>
/// <param name = "oldValue"> Reference to the property value field. </param>
/// <param name = "newValue"> New value. </param>
/// <param name = "propertyName"> The name of the property. </param>
/// <remarks> If the base method is not called in the derived class,
/// then the value will not change.</remarks>
protected virtual void OnValueChange<T>(ref T oldValue, T newValue, string propertyName)
{
oldValue = newValue;
RaisePropertyChanged(propertyName);
}
}
视图模型
public class ViewModelName : BaseINPC
{
private ModelName model = new ModelName();
public ViewModelName()
=> model.NameChangedEvent += NameChangedMethod;
private void NameChangedMethod(object sender, string newName)
=> Name = newName;
private string _name;
public string Name { get => _name; set => Set(ref _name, value); }
protected override void OnValueChange<T>(ref T oldValue, T newValue, string propertyName)
{
base.OnValueChange(ref oldValue, newValue, propertyName);
if (propertyName == nameof(Name))
model.SendName(Name);
}
}