1

它的解释方式是通过使用事件和发布/订阅模型。基本上,模型只是数据,它不知道视图/GUI/UI。模型通常只是一个抽象对象,它对其数据进行操作,并且可以执行操作等等。

视图是一个不同的类,它响应模型中的变化并且通常将这些数据显示给用户。以前,我不知道如果没有视图和模型之间的耦合,这怎么会发生,但是用事件解释它可以消除很多混乱。这是否意味着模型包含在发生有趣事情时自身引发的公共事件?例如,如果我们正在编写一个国际象棋游戏,当一个棋子被移动时,模型将PieceMoved使用必要的信息(哪一个棋子,从哪里移动到哪里等)引发事件,并且视图可以订阅这样一个事件,然后显示作品从旧方块移动到新方块的动画。

仍然让我感到困惑的部分是控制器的确切性质。我无法理解它如何为模型和视图提供新信息。我想控制器包含对模型和视图的引用。与国际象棋示例保持一致,控制器是否会仅响应用户输入(例如移动棋子),然后仅向模型建议要移动的棋子到哪里?然后模型获取这些信息,查看它是否是合法的移动,如果是,相应地更新模型,引发PieceMoved事件,视图对此做出反应并相应地更新图形领域?

最后,控制器如何找出试图移动的部分?似乎这种类型的东西与视图密切相关(假设移动涉及首先单击您要移动的部分,然后单击目标方块)。我想控制器会响应鼠标点击并将这些坐标发送给模型,但是模型如何知道如何转换这些坐标以找到选择了哪一块?这不是与视图密切相关吗?看起来视图必须执行一些逻辑处理,而不是简单地响应模型和控制器,但它不再是正确的视图(而是视图/模型组合)。

4

4 回答 4

0

MVC 是一个非常通用的概念。它有很多不同的实现方式,其中大多数都有某种妥协。

我看到的问题是您正试图采用一个深奥的概念并将具体的实现细节应用于它。这很难做到,除非您有一个非常具体的实现(asp.net MVC、fubuMVC、spring MVC、smalltalk MVC 等等),并且每个实现都以不同的方式完成通知和事件处理之类的事情。

如果您只是在谈论 MVC 概念,那么您必须以通用的方式处理 MVC 概念。我知道如果你有一个具体的实现可能会更容易理解,但是你会根据对实现的理解走上理解模式(MVC)的道路,这可能会扭曲你对模式本身的理解。

因此,当您阅读有关消息或事件的信息时,您只需要考虑“某种由实现定义的机制”。它可能是一个回调,或者它可能是一个 C# 事件,或者它可能是一个 Windows 消息,或者它可能正在使用强制 ;)

编辑:

关于您的更新,我会重复一遍。您无法回答有关通用概念的实现特定细节。您必须定义一个特定的实现,以便有人能够告诉您这些实现细节是如何完成的。

于 2012-09-06T21:48:53.840 回答
0

这个问题有很多答案,主要是因为有太多不同的 MVC 框架。查看http://martinfowler.com/eaaDev/uiArchs.html获取一些示例。我也可以给出一个 MVVM 的观点,主要是因为这是我这些天一直在做的事情,所以这就是我的想法。

模型层基本上是您的数据和业务逻辑。您可能在这里与数据库或 Web 服务通信。如果您最终编写了一个系统,而不仅仅是一个 GUI,那么这就是您的可重用代码。

然后 ViewModel 位于 Model 之上,基本上将数据呈现(咳咳)作为属性。它使用 INotifyPropertyChanged 接口在数据更改时通知 UI。如果在将数据推送到模型层之前,您有用于构建某些东西的数据,那么它就存在于此。您通常会将可以在 UI 中执行的操作公开为 ICommands。

View 层是耦合度最低的,因为它只是使用绑定来连接 ViewModel。要可视化的东西是与用于更改其形式的可选 IValueConverters 绑定的属性,例如

Visibilty="{Binding IsVisible, Converter={StaticResource booleanToVisibiltyConverter}}"

操作 UI 元素绑定到 ViewModel 上的命令以启动 ViewModel 操作。

Command="{Binding DoSomething}"
于 2012-09-06T22:10:38.590 回答
0

MVC 模式的坏处是:

  • 每个人都有她/他自己的版本
  • 刚开始理解有点抽象

好东西:

  • 其实很简单
  • 这是划分大多数应用程序的绝佳方式

不过要回答你的问题:

该模型

这是一个容易的。模型应该只知道它自己。它是棋盘棋子和游戏规则。如果您可以在桌面应用程序或 Web 应用程序中重用它,您就知道您正在构建您的模型。

风景

这也不复杂。它是视觉部分,也是处理用户输入的部分。理解视图在 MVC 模式中的作用的最重要的概念是它们必须提供一种方法来调用系统的公共接口。在国际象棋游戏中,它必须绘制元素并检测用户使用鼠标/键盘在做什么。当用户做某事时,视图负责调用系统:例如。“用户 1 想将块从 X 移动到 Y”(重要提示:大多数时候,您不希望视图触发像用户 1 在坐标 x、y 中单击的调用。像素是视图的领域。系统必须接收与图形表示方式无关的订单)。

控制器

你是对的,这个不是那么直截了当。控制器是必须处理对系统公共接口的调用的控制器。在您的示例中,它将收到一个调用“User1 从 X 移动到 Y”并调用模型的适当对象中的一个方法(在这种情况下很可能是)。因此,控制器完全了解模型中的对象。但是,它也可以包含应用程序中必需但不属于您的模型域的代码。您必须检查用户是否有权访问系统?您必须将该调用记录到文件中吗?好吧,大多数时候这种东西都会进入控制器。

然而,这只是我自己的 MVC 版本(我和其他人一样,也有我自己的...... :)

于 2012-09-06T22:24:40.663 回答
-1

因此,如果您有一个视图(棋盘)和一个用于棋盘的控制器,控制器将为它存储事件。当您移动一块时,它会引发PieceMoved事件,该事件应将信息传递给该事件,例如当前位置和所需位置。

对于一个非常简单的应用程序,您可能无法掌握模型的概念。一个人可能有一个可以在多个视图(例如详细信息和创建视图)上重复使用的计费模型。您不希望每次需要时都复制此代码,因此在您的控制器中,每个事件都会联系到需要它的计费模型。通过创建模型,您可以封装您的代码。

于 2012-09-06T21:54:58.537 回答