【问题标题】:What constitutes a viewmodel?什么构成视图模型?
【发布时间】:2013-09-11 04:29:03
【问题描述】:

我仍然不完全确定什么是视图模型。我有一个类用于包装我的模型并稍微更改数据,但我不确定它是否构成视图模型。什么是必要的视图模型?它只是不应该直接依赖于视图,因此视图模型不知道视图如何使用其属性并且视图不知道视图模型中的内容吗?当视图想要更新任何东西时,它只是给出了一些抽象命令,视图模型采用并使用它来更新模型?

据我在 MVVM 中的理解,我应该在视图上使用绑定到视图模型上的属性的属性,这些属性绑定到模型上的属性。

在相反的方向上,我应该使用从视图到视图模型的命令,然后它可以使用 Icommand 来命令模型,或者可以只调用模型中的公共函数来对其进行更改。

一个令人困惑的事情是,在我看到的 MVVM 示例中,看起来就像在 MVVM 中一样,除了可能创建命令之外,视图应该没有任何代码,但我不知道如何在我当前的项目中做到这一点.我正在使用许多与事件交互的控件来制作自定义控件。

如何在不使用事件的情况下让一个树视图在另一个树视图的展开上展开?

【问题讨论】:

    标签: wpf mvvm


    【解决方案1】:

    通常,视图模型最终与您的领域模型非常相似。拥有视图模型的主要目标之一是将 GUI 开发与业务逻辑分开。例如,假设您有一个“用户”域模型,该模型具有您不希望向视图公开的 IsAdmin 属性。您创建了一个名为“UserViewModel”的视图模型,它仍然具有 ID、用户名和密码(参见下面的示例代码),但没有 IsAdmin 属性。另一种方法是在视图模型中使用域模型,请参阅下面的“AlternateUserViewModel”类。任何 View Model 解决方案都有利有弊。创建具有属性的 UserViewModel 类意味着您实际上是在复制为域模型创建的对象,因为您的域模型通常与您的视图模型非常相似。使用 AlternateUserViewModel 方法,业务逻辑层和 GUI 层之间没有明确的分离,因为视图模型仍然需要“了解”域模型。您决定采用哪种方法实际上取决于您工作的环境。对于个人项目,我喜欢使用第二种方法,因为将业务逻辑与设计层分开并不是我不想让的主要问题视图模型层“看到”领域模型层,但对于在设计层和后端有独立团队工作的大公司,第一种方法可能是首选。

    public class User
    {
        public int ID { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }
        public bool IsAdmin { get; set; }
    }
    
    public class UserViewModel
    {
        public int ID { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }
    }
    
    public class AlternateUserViewModel
    {
        public User User { get; set; }
    
        public User ToDomainModel()
        {
            if (User == null)
                return null;
    
            // if this is an existing user, retrieve it from the database so you're not overwriting the IsAdmin property
            if (User.ID != default(int))
            {
                User existingUser = UserService.GetUserByID(User.ID);
                existingUser.Username = User.Username;
                existingUser.Password = User.Password;
                // IsAdmin is not set because you don't want that property exposed in the View Model
                return existingUser;
            }
            else
            {
                return new User
                           {
                               Username = User.Username,
                               Password = User.Password,
                               IsAdmin = false
                           };
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      您在这里有很多问题(考虑将其分成多个帖子)。我会试着回答一些。

      我认为 ViewModel 是 THE 应用程序,换句话说,这是应用程序的大部分逻辑发生的地方。

      换句话说,ViewModel 接收以下输入:

      • 视图中的命令
      • 视图中绑定属性的更改
      • 来自后台服务的事件(例如,从 Web 接收数据时)
      • 来自系统或领域模型的其他事件

      并生成以下输出:

      • 更改视图将绑定到的属性(例如,IsBusy 可能导致视图显示等待指示器)
      • 在视图中显示/隐藏内容(当然是间接的,例如使用各种 bool 属性)
      • 导致导航到其他视图(也是间接的,因为它无法直接访问视图可用的NavigatonService)。

      看待 ViewModel 的另一种方式是这样的:ViewModel 是系统的完整面向用户的状态。换句话说,视图将使用此状态而不是其他任何内容以某种用户可理解的方式显示/呈现此状态。

      关于命令与事件:

      不幸的是,并非 WPF 中的所有内容都公开为 Command。按钮生成Commands,但并非所有控件都这样做。 幸运的是,您可以使用行为将事件转换为命令,并且一些框架提供了实现。这是 MVVM Light 如何做到这一点的example。 Blend 也提供了这个functionality

      另外,为什么需要在代码隐藏中生成Commands?像 MVVMLight 这样的框架提供了RelayCommand(或DelegateCommand)的实现,无需创建不同的ICommand 实现。您也可以轻松implement it yourself

      【讨论】:

        猜你喜欢
        • 2011-05-12
        • 1970-01-01
        • 2012-09-15
        • 1970-01-01
        • 2011-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-03
        相关资源
        最近更新 更多