构成视图模型的是什么?

时间:2013-09-07 00:34:30

标签: wpf mvvm

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

正如我在MVVM中所理解的那样,我应该在视图上使用绑定到viewmodel上绑定到模型属性的属性的属性。

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

令人困惑的是,在MVVM的例子中,我看到它在MVVM中看起来应该没有代码,除了可能创建命令,但我不知道如何在我当前的项目中做到这一点。我正在使用大量与事件交互的控件进行自定义控件。

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

2 个答案:

答案 0 :(得分:2)

通常,View Models最终与您的域模型非常相似。使用View Models的主要目标之一是将GUI开发与业务逻辑分开。例如,假设您有一个“用户”域模型,该模型具有您不希望暴露给View的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
                       };
        }
    }
}

答案 1 :(得分:1)

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

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

换句话说,ViewModel接收输入:

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

并生成输出:

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

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

关于命令与事件:

不幸的是,并非WPF中的所有内容都以Command公开。按钮生成Command,但不是所有控件都生成。 幸运的是,您可以使用“行为”将事件转换为命令,而某些框架则提供实现。这是MVVM Light如何做到的example。 Blend还提供此functionality

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