【问题标题】:WPF MVVM - using model in view model classWPF MVVM - 在视图模型类中使用模型
【发布时间】:2011-02-04 15:26:37
【问题描述】:

我想知道在视图模型中正确使用模型类的方法。作为 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; }
}

【问题讨论】:

  • 您可以通过使用深度属性绑定来大大缩短第一种方法,即,只需将元素绑定命名为“CurrentUser”“CurentUser_Nick”的“Nick”字符串(对于 CurrentUser_Password 也是如此) - 然后你根本不需要属性“CurrentNick”和“CurrentPassword”(不过,请将 NotifyOfPropertyChange 添加到 CurrentUser)。

标签: wpf mvvm caliburn.micro


【解决方案1】:

第一个替代方案会更好,因为它可以更好地从 View 封装您的模型。
但是您应该在 ViewModel上实现 IDataErrorInfoINotifyPropertyChanged >,因为 ViewModel 应该是通知用户界面更改和错误的对象。

【讨论】:

  • 所以最好在视图模型类上实现IDataErrorInfo,这个我不知道。
  • 是的,当然。此外,在 WPF 中,您可以在 Bindings 上设置 ValidatesOnDataErrors=True,它们将自动使用 ViewModel 在该属性名称上提供的错误信息。
【解决方案2】:

我更喜欢第一种方法。有几个原因:

  • Model 不应该被 View 访问。
  • 理论上,ViewModel 包装/外观需要从Model 绑定到View 的所有属性。它添加了促进View 的功能所需的任何其他属性、集合和命令,同时防止将代码放在代码后面。
  • IDataErrorInfoINotifyPropertyChanged 促进 View 而不是 ViewModel。由于View 只与ViewModel 通信,所以它们应该在ViewModel 内部。

【讨论】:

    【解决方案3】:

    我会使用 second 方法。如果您正在寻找使用第二种方法的示例应用程序,那么您可能会发现 WPF Application Framework (WAF) 项目很有趣。

    【讨论】:

      【解决方案4】:

      我建议从第二种方法开始。它可以使您免于输入大量重复的桥接属性。如果您遇到需要在 View Model 上包装的属性,请为该属性执行此操作,然后更新 View 的绑定。您的模型和视图模型都可以实现 IDataErrorInfo 和 INotifyPropertyChanged。当模型中的某些逻辑更改属性时,后者非常有用,因为它将被传播到视图。通过基类实现这些接口,您可以同时拥有 ModelBase 和 ViewModelBase 抽象类,后者派生自前者。

      【讨论】:

      • 请注意,这不是MVVM。您将违反为MVVM 创建的几乎所有准则。而且,ViewModel 永远不会继承自 Model
      • @decyclone:我认为您的意思是,当您说视图不应直接引用模型时,我违反了您在回答中强调的一条准则。虽然我在其他地方看到过,但这对 MVVM 来说绝不是必不可少的。
      • 请查看这篇文章以供参考:msdn.microsoft.com/en-us/magazine/dd419663.aspx 并自行决定违反了多少准则。
      • 这是一篇很棒的文章,我也推荐它作为 MVVM 的介绍。不过,我看不出在此处发布链接如何进一步说明您的观点。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-14
      • 1970-01-01
      • 2020-01-17
      • 1970-01-01
      • 1970-01-01
      • 2011-10-07
      相关资源
      最近更新 更多