我对 WPF 相当陌生。我的理解是模型中的数据发生变化,它应该通知 View 模型,并且 View 将绑定(bind)到 View 模型中的属性和类似的东西。它是否正确?如果是这样,我一直在阅读该模型应该实现 INotifyPropertyChanged
,看起来像这样
public class LoginModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
public bool Authenticated { get; set; }
}
在我的 ViewModel 中,我有一个属性“AuthResult”,它应该从模型属性“Authenticated”中获取更新
public partial class view1 : UserControl, INotifyPropertyChanged{
public bool AuthResult
{
get
{
return _authVal;
}
set
{
_authVal = value;
NotifyPropertyChanged("AuthResult");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
}
我知道这个当前的实现是不正确的。我发现我应该从我的模型订阅 PropertyChanged 通知,如下所示:
LoginModel.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(LoginModel_PropertyChanged);
void LoginModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if(e.PropertyName == "Authenticated")
{
//do something
}
}
我看不到应该在哪里更新“AuthResult”属性。我会在 If 语句中做些什么,比如
AuthResult = _model.Authenticated;
?编辑:
在我的构造函数中?
LoginModel _model;
public view1(LoginModel model)
{
_model = model;
InitializeComponent();
}
最佳答案
如果模型实现了 INotifyPropertyChanged 接口(interface),您可以从 View 直接绑定(bind)到它:
<Button Content="Button" IsEnabled="{Binding Authenticated}" />
请注意,只要将 Authenticated 属性设置为新值,LoginModel 类就必须引发 PropertyChanged 事件。
您还可以通过 View 模型类公开整个模型实体:
public class ViewModel
{
public ViewModel(LoginModel model)
{
Model = model;
}
public LoginModel Model { get; }
}
...并像这样绑定(bind)到它:
<Button Content="Button" IsEnabled="{Binding Model.Authenticated}" />
它仍然是模型类,必须实现 INotifyPropertyChanged 接口(interface)并引发更改通知。
另一种选择是让 View 模型包装您希望能够从 View 绑定(bind)到的模型类的任何属性。然后绑定(bind)到 View 模型类的属性,该属性又包装模型类的属性,如下所示:
public class ViewModel
{
private readonly LoginModel _model;
public ViewModel(LoginModel model)
{
_model = model;
}
public bool AuthResult
{
get
{
return _model.Authenticated;
}
set
{
_model.Authenticated = value;
NotifyPropertyChanged("AuthResult");
}
}
}
<Button Content="Button" IsEnabled="{Binding AuthResult}" />
使用后一种方法的好处是 View 不依赖于模型类。它只绑定(bind)到 View 模型类,这就是 MVVM 设计模式的典型实现方式。
但是,如果您确实绑定(bind)到 View 模型的(包装器)属性并希望在设置模型类的属性时更新 View ,则模型必须通知 View 模型它已经以一种或另一种方式更改,即它必须引发某种事件或类似事件。这通常意味着实现 INotifyPropertyChanged 接口(interface)。然后, View 模型可以订阅模型的 PropertyChanged 事件,并在模型更新时为数据绑定(bind)属性引发自己的 PropertyChanged 事件,例如:
public class ViewModel
{
private readonly LoginModel _model;
public ViewModel(LoginModel model)
{
if (model == null)
throw new ArgumentNullException("model");
_model = model;
_model.PropertyChanged += OnModelChanged;
}
private void OnModelChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Authenticated")
NotifyPropertyChanged("AuthResult");
}
public bool AuthResult
{
get
{
return _model.Authenticated;
}
set
{
_model.Authenticated = value;
NotifyPropertyChanged("AuthResult");
}
}
}
关于wpf - 从模型更新 ViewModel 中的属性的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41347515/