WPF MVVM-在视图模型类中使用模型

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

我想知道在视图模型中正确使用模型类是什么。作为MVVM,我使用Caliburn Micro

第一种选择。

模型类:

    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)。