14

在基于 mvc 的大系统中,有负责编辑数据的视图和显示该数据的视图。

示例:UserManagementViewUserSelectionView

每个子系统应该知道它是否需要数据更新,在另一个子系统对相同的数据进行了更改之后,以便它的控制器知道是否需要数据更新。

我对此的想法类似于观察者模式(有点集成在 c# 中),所有控制器都将是侦听器,最终会收到发生数据操作的通知。

BindingList<>例如提供一个ListChanged事件。类似地,可以为每个数据结构创建一个接口,并将更改通知控制器。这会增加开销(IMO),我发现这个解决方案很难在大型系统中维护,无论如何更新数据也不是解决方案。

哪种架构设计可以在这种情况下提供帮助?

4

4 回答 4

5

这个问题听起来像你试图在没有模型部分的情况下使用 MVC。如果我误解了,编辑您的问题以包含实际用例(示例)可能有助于我们理解上下文。

但总的来说,没有什么应该真正持久/存储在您的控制器中。所以控制器中不应该有任何需要“更新”或“通知”的内容(即:没有数据)。相反,数据应该位于管理所有数据的单独“模型”层中。然后视图从模型层读取以获取该视图的任何数据。

如需快速复习,请查看MVC 上的 wikipedia 页面,该页面有一个很好的经典 MVC 流程图和关于组件交互的简单文章。

讨论示例

让我们试着设计一个例子来理解这个问题。

假设我的应用程序中有一个用户列表。此列表可能显示在:

  • 主管理员列表视图
  • 管理员编辑用户视图
  • 用户的个人资料视图
  • 也许更多?

这些视图中的每一个都将从您的模型层请求数据并在屏幕上显示一些内容。

现在假设对一个用户的配置文件进行了更改。这将通过一个控制器方法来完成,该方法执行任何必要的工作以将一些更改应用于模型。

我的理解是,您希望所有这些视图都更新以反映这种变化。这意味着视图需要从模型中重新加载数据。它不应该从控制器本身获取此数据,即使控制器触发此重新加载/刷新 - 或者更确切地说,控制器方法可能有助于从您的模型层进行查询。重要的是,您不会在整个应用程序的多个控制器中维护数据的多个副本。持久性集中在模型层。

在 winforms 的情况下,如果您的 UI 组件被构建为识别该接口并相应地刷新,模型层可能能够提供类似于提到的 INotifyPropertyChanged 接口的东西。但这是一种相当依赖平台的方法。

一种更加平台/上下文不可知的方法是已经提到的发布-订阅(发布-订阅)模式。在这种情况下,对模型进行更改的每个控制器方法也会发布其更改的通知。该数据的任何视图都可以通过从模型层刷新/重新加载视图数据来监听并响应此类通知。

于 2012-08-29T06:45:39.593 回答
3

为什么不直接使用 .NET 中内置的事件模型?我没有正确理解这个问题吗?您的问题表明您认为这会增加很多“开销”(不清楚您是指性能还是开发),但从性能的角度来看,这个解决方案非常轻量级。

class YourModel
{
    //---- event class can contain data elements to update listeners
    public class DataChangedEventArgs : EventArgs
    {
        ...
    }

    //---- this is what the client callback need to look like
    public delegate void DataChangedDelegate(object oSender, DataChangedEventArgs args);

    //---- public event that clients subscribe to
    public event DataChangedDelegate evtDataChanged;

    //---- any changes in YourModel invoke this method to notify clients
    protected void OnChanged(DataChangedEventArgs args)
    {
        if (evtDataChanged != null)
            evtDataChanged(this, args);
    }

    //---- method(s) in your Model that change internal data
    public void ImaDataChanger(...) 
    {
        //---- stuff that changes the data

        OnChanged(args);    //-- notify clients
    }
}

class UserSelectionView
{
    //---- the event callback
    public void DataChangedHandler(object oSender, YourModel.DataChangedEventArgs args)
    {
        //---- process update or refresh data
        //---- UI updates will have to be marshalled to the UI thread
    }

    //---- sign up for events
    public void Subscribe(YourModel model)
    {
        model.evtDataChanged += new YourModel.DataChangedDelegate(DataChangedHandler);
    }
}

您可以选择定义其他事件或将数据成员添加到 DataChangedEventArgs 以提供有关数据更改类型的信息。

此外,如下面的评论所示,如果您需要将视图放在不同的计算机上或同一台计算机上的不同进程中,您可以使用 .NET Remoting 来实现这一点,只需对代码进行很少的更改。

于 2012-08-29T06:34:36.873 回答
3

我知道 WPF 与 MVVM 的结合在很大程度上依赖于INotifyPropertyChanged和额外的INotifyCollectionChanged. 也许这个简单的界面可能会为您解决问题。

在此处阅读有关此内容。Josh Smith 的一篇关于 MVVM 基础知识的文章,您可以在其中了解INotifyPropertyChanged. 虽然它在 WPF 环境中,但它也可以在 WinForms 中使用。

于 2012-08-28T12:42:13.037 回答
3

我已经成功地使用了发布-订阅模式来解决这类问题。每当有人修改某些人可能有兴趣知道的内容时,您就会引发“ObjectWasModified”事件,或者如果您想要更具体的事件,例如“NewUserAdded”等……然后,每个子系统或其他需要知道的事情何时发生发生时,它订阅该类型的事件。您可以将模板参数添加到 Event ObjectWasModified 或附加条件中,这样每个系统只接收它真正感兴趣的事件。

于 2012-07-09T03:18:37.330 回答