65.9K
CodeProject 正在变化。 阅读更多。
Home

建模 M-V-VM

2009年6月5日

CPOL

2分钟阅读

viewsIcon

27514

downloadIcon

327

本文试图提出一种解耦 M-V-VM ViewModel 对象的方法。

引言

构建基于 M-V-VM 的应用程序非常方便。本文旨在介绍一种通用的 View Model 解耦方法。 

背景

使用 WPF 构建 UI 应用程序时,M-V-VM 是一种将数据与其表示形式解耦的绝佳机制。每个 UI 组件,无论是 Window、Page 还是 User Control,都有自己的 view model。大多数应用程序具有与 View 结构相对应的层次结构。因此,包含 User Control 的 Page 会将其 view model 保留为 User Control 的 View Model 作为类成员。当我想让控件中的某个动作对应用程序的其他部分产生影响时,我的问题就开始了。我过去的做法是在后代 View Model 中有一个“Parent”属性。这在过去一直有效,直到我想在应用程序的新部分中重用该控件。然后我意识到使用这种方法限制了我的代码可重用性。我注意到解耦应该在 View Model 本身完成,而不仅仅是在 View 和 View Model 之间完成。那时我提出了“IViewModel”解决方案。

我开始将不同的 View Model 视为独立的单元,因此不应该持有关于其发起者的任何知识。我的解决方案是创建 IViewModel 接口。使用此接口使 View Model 能够执行两件事: 

  1. 通知 View Model 在其他 View Model 的 View 上发生的事件。
  2. 从应用程序的其他部分使用服务。

事件通知很容易理解,但是第二部分有点令人困惑。应用程序通常不是独立的,而是与外部范围(例如 DB 或远程服务)保持连接。我更喜欢为这些服务保留一个单点。

IVIewModel

IViewModel 是一个简单的接口: 

/// <summary>
/// An interface which enables event routing via the view models
/// </summary>
public interface IViewModel
{
    /// <summary>
    /// A property which gets the View model's Parent
    /// </summary>
    IViewModel VMParent
    {
        get;
    }
     /// <summary>
    /// A method which is used for handling events.
    /// </summary>
    /// <param name="sender">The original sender</param>
    /// <param name="param">an attached parameter used for sending data</param>
    /// <param name="viewModelEvent">an Enum which represents the name of 
    /// the event which needs to be taken care of</param>
    void HandleEvent(IViewModel sender, object param, 
			ViewModelOperationsEnum viewModelEvent);
}

应用程序中的每个 ViewModel 类都实现此接口。如果 View model 只是其子项及其父项之间的管道,则 handle event 实现通常如下所示

public void HandleEvent(IViewModel sender, 
	object param, ViewModelOperationsEnum viewModelEvent)
{
     if (VMParent != null)
     {
        VMParent.HandleEvent(sender, param, viewModelEvent);
     }
} 

使用应用程序

该应用程序由四个项目组成,客户端两个,服务器端两个。 应用程序运行时,将出现两个窗口,一个包含 TreeView 对象的 GUI 窗口和一个控制台窗口。 将这两个窗口并排放置。 打开树视图节点并解析这些节点。 您会注意到每个节点都向服务器发出请求。 这是在节点不了解服务器的任何信息的情况下完成的。 

历史

  • 2009 年 5 月 29 日:首次发布
© . All rights reserved.