0

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

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

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

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

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

4

2 回答 2

2

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

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

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

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

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

并生成以下输出:

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

考虑 ViewModel 的另一种方式是这样的:ViewModel 是系统的完整的面向用户的状态。换句话说,视图将不会使用此状态来以某种用户可理解的方式显示/呈现此状态。

关于命令与事件:

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

另外,为什么需要Command在代码隐藏中生成 s ?像 MVVMLight 这样的框架提供了一个RelayCommand(或DelegateCommand)的实现,它消除了创建不同ICommand实现的需要。您可以自己轻松实现它

于 2013-09-07T02:27:04.950 回答