WPF MVVM-在视图模型类中使用模型
我想知道在视图模型中正确使用模型类是什么。作为MVVM,我使用Caliburn Micro 第一种选择。 模型类:WPF MVVM-在视图模型类中使用模型,wpf,mvvm,caliburn.micro,Wpf,Mvvm,Caliburn.micro,我想知道在视图模型中正确使用模型类是什么。作为MVVM,我使用Caliburn Micro 第一种选择。 模型类: public class CurrentUser : IDataErrorInfo { public string Nick { get; set; } public string Password { get; set; } //... } [Export(typeof(ILogOnViewModel))] public
public class CurrentUser : IDataErrorInfo
{
public string Nick { get; set; }
public string Password { get; set; }
//...
}
[Export(typeof(ILogOnViewModel))]
public class LogOnViewModel : Screen
{
public CurrentUser CurrentUser { get; set; }
//bind on control in view
public string CurrentNick
{
get { return CurrentUser.Nick; }
set
{
CurrentUser.Nick = value;
NotifyOfPropertyChange(() => CurrentNick);
}
}
//bind on control in view
public string CurrentPassword
{
get { return CurrentUser.Password; }
set
{
CurrentUser.Password = value;
NotifyOfPropertyChange(() => CurrentPassword);
}
}
}
public class CurrentUser : IDataErrorInfo, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public string Nick
{
get { return _nick; }
set
{
_nick = value;
NotifyPropertyChanged("Nick");
}
}
public string Password
{
get { return _password; }
set
{
_password = value;
NotifyPropertyChanged("Password");
}
}
//...
}
[Export(typeof(ILogOnViewModel))]
public class LogOnViewModel : Screen
{
//bind on UI control
public CurrentUser CurrentUser { get; set; }
}
使用视图模型类中的模型:
public class CurrentUser : IDataErrorInfo
{
public string Nick { get; set; }
public string Password { get; set; }
//...
}
[Export(typeof(ILogOnViewModel))]
public class LogOnViewModel : Screen
{
public CurrentUser CurrentUser { get; set; }
//bind on control in view
public string CurrentNick
{
get { return CurrentUser.Nick; }
set
{
CurrentUser.Nick = value;
NotifyOfPropertyChange(() => CurrentNick);
}
}
//bind on control in view
public string CurrentPassword
{
get { return CurrentUser.Password; }
set
{
CurrentUser.Password = value;
NotifyOfPropertyChange(() => CurrentPassword);
}
}
}
public class CurrentUser : IDataErrorInfo, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public string Nick
{
get { return _nick; }
set
{
_nick = value;
NotifyPropertyChanged("Nick");
}
}
public string Password
{
get { return _password; }
set
{
_password = value;
NotifyPropertyChanged("Password");
}
}
//...
}
[Export(typeof(ILogOnViewModel))]
public class LogOnViewModel : Screen
{
//bind on UI control
public CurrentUser CurrentUser { get; set; }
}
第二种选择:
模型类:
public class CurrentUser : IDataErrorInfo
{
public string Nick { get; set; }
public string Password { get; set; }
//...
}
[Export(typeof(ILogOnViewModel))]
public class LogOnViewModel : Screen
{
public CurrentUser CurrentUser { get; set; }
//bind on control in view
public string CurrentNick
{
get { return CurrentUser.Nick; }
set
{
CurrentUser.Nick = value;
NotifyOfPropertyChange(() => CurrentNick);
}
}
//bind on control in view
public string CurrentPassword
{
get { return CurrentUser.Password; }
set
{
CurrentUser.Password = value;
NotifyOfPropertyChange(() => CurrentPassword);
}
}
}
public class CurrentUser : IDataErrorInfo, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public string Nick
{
get { return _nick; }
set
{
_nick = value;
NotifyPropertyChanged("Nick");
}
}
public string Password
{
get { return _password; }
set
{
_password = value;
NotifyPropertyChanged("Password");
}
}
//...
}
[Export(typeof(ILogOnViewModel))]
public class LogOnViewModel : Screen
{
//bind on UI control
public CurrentUser CurrentUser { get; set; }
}
在视图模型类中使用模型类:
public class CurrentUser : IDataErrorInfo
{
public string Nick { get; set; }
public string Password { get; set; }
//...
}
[Export(typeof(ILogOnViewModel))]
public class LogOnViewModel : Screen
{
public CurrentUser CurrentUser { get; set; }
//bind on control in view
public string CurrentNick
{
get { return CurrentUser.Nick; }
set
{
CurrentUser.Nick = value;
NotifyOfPropertyChange(() => CurrentNick);
}
}
//bind on control in view
public string CurrentPassword
{
get { return CurrentUser.Password; }
set
{
CurrentUser.Password = value;
NotifyOfPropertyChange(() => CurrentPassword);
}
}
}
public class CurrentUser : IDataErrorInfo, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public string Nick
{
get { return _nick; }
set
{
_nick = value;
NotifyPropertyChanged("Nick");
}
}
public string Password
{
get { return _password; }
set
{
_password = value;
NotifyPropertyChanged("Password");
}
}
//...
}
[Export(typeof(ILogOnViewModel))]
public class LogOnViewModel : Screen
{
//bind on UI control
public CurrentUser CurrentUser { get; set; }
}
第一种选择会更好,因为它能更好地从视图中封装您的模型。
但是您应该在ViewModel上实现
IDataErrorInfo
和INotifyPropertyChanged
,因为ViewModel应该是通知用户界面更改和错误的对象 我更喜欢第一种方法。原因如下:
视图不应访问
模型
- 理论上,一个
包装了所有需要从ViewModel
绑定到Model
的属性。它添加了任何额外的属性、集合和命令,以方便查看View
的功能,同时防止代码被隐藏
和IDataErrorInfo
方便INotifyPropertyChanged
非查看
。由于视图模型
仅与View
通信,因此它们应该位于ViewModel
内部ViewModel
- 我建议从第二种方法开始。它可以避免您键入大量重复的桥接属性。如果遇到需要在视图模型上包装的属性,请对该属性进行包装,然后更新视图的绑定。模型和视图模型都可以实现IDataErrorInfo和INotifyPropertyChanged。当模型中的某些逻辑更改属性时,后者非常有用,因为它随后将传播到视图。通过基类实现这些接口,您可以同时拥有ModelBase和ViewModelBase抽象类,后者源自前者。我将使用第二种方法。如果您正在寻找使用第二种方法的示例应用程序,那么您可能会发现项目很有趣。因此最好在视图模型类上实现IDataErrorInfo,我不知道。是的,肯定是这样。此外,在WPF中,您可以在绑定上设置validatesOnDaerRors=True,它们将自动使用ViewModel在该属性名称上提供的错误信息。请注意,这不是
MVVM
。您将违反为MVVM
创建的几乎所有准则。而且,永远不要,ViewModel
继承自Model
@declone:我想你的意思是我打破了你在回答中强调的一条准则,当时你说视图不应该直接引用模型。尽管我在其他地方看到过这一点,但它对MVVM来说并不是必不可少的。请阅读本文以供参考:并自行决定有多少准则被违反。这是一篇很棒的文章,我也推荐它作为MVVM的介绍。不过,我不知道在这里发布链接如何进一步说明您的观点。通过使用深度属性绑定,您可以大大缩短第一种方法,即,只需将元素绑定命名为“CurrentUser”“CurrentUser\u Nick”的“Nick”字符串(CurrentUser\u Password也是如此)“-那么您根本不需要属性‘CurrentNick’和‘CurrentPassword’(不过将NotifyOfPropertyChange添加到CurrentUser)。