繁体   English   中英

该模型应如何在MVVM中实现?

[英]How should the model be implemented in MVVM?

我正在创建一个与一个或多个服务进行通信的简单网络应用程序,因此我计划使用一些队列(用于传出消息和传入消息),一个表,一个包含每个活动连接状态的列表等。换句话说,这些是确保应用程序本身运行所需的数据结构。

此应用程序还必须配备图形界面,以显示应用程序本身内部功能的一部分:例如,队列的填充状态,连接状态(检测到的速度等)等。 Model-View-ViewModel模式,模型由要在GUI中显示的数据组成:在此应用程序中,上述数据结构表示模型。 换句话说, 模型实现了应用程序的业务逻辑。

ViewModel应该实现INotifyPropertyChanged接口,以便通知View发生了更改,但是Model如何与ViewModel通信? 阅读本文之后 ,我意识到INotifyPropertyChanged接口是由模型实现的。 这个答案可以解释更多,但是让我有些困惑:

INotifyPropertyChanged-应该进入ViewModel和Model(如果需要)

为什么, 如果需要 什么时候应该实现此接口? 什么时候不应该实施?

而且, Dictionary不实现INotifyPropertyChanged接口:如果我使用它,是否应该将它与实现此接口的类包装在一起?

最后,该模型应该是只读的,这意味着用户无法使用GUI更改内部数据结构的内容。 如何做到这一点?

how does the Model to communicate with the ViewModel

您想要的任何方式。 在我们编写的大多数应用程序中,视图模型都调用业务逻辑层(模型)。 但是,如果需要立即将视图更改通知(事件)视图模型,则可以在模型上实现INotifyPropertyChanged。 或者,您可以简单地使视图模型订阅模型上的事件。

Moreover, the Dictionary does not implement the INotifyPropertyChanged interface: if I use it, should I wrap it with a class which implements this interface?

您只需要使视图模型实现INotifyPropertyChanged。 视图模型(字典)中的属性将仅调用NotifyPropertyChanged(或实现的任何形式)。

Finally, the model should be read-only, meaning that the user does not be able to change the contents of internal data structures using the GUI. How to accomplish this?

不要为用户提供让他们更改数据的功能。 使绑定成为一种方式,或者干脆不为他们提供进行更改的API。

  1. INotifyPropertyChanged主要由ViewModel类实现。 这是为了促进数据绑定,以便在修改属性后,将更新绑定到ViewModel属性的视图中的UI控件。
    在MVVM设计模式中,关系非常简单并且在一个方向上。 View知道它是ViewModel,而ViewModel知道该模型。 如果更新了Model,则ViewModel需要知道某种方式,以便它可以反映更新并将其传播到View。 一种方法是让Model实现INotifyPropertyChanged并让ViewModel实现相应的事件处理程序。 如果所有更改都是从UI驱动并推回模型,则可能没有必要。

  2. 您无法真正绑定到字典。 如果可以的话,最好使用ObservableCollection。 或者,您可以按照以下方式看一下如何实现可观察词典: http : //drwpf.com/blog/2007/09/16/can-i-bind-my-itemscontrol-to-a-dictionary/

  3. MVVM提供了模型与视图的分离,因此视图与模型之间不应存在直接关系。 ViewModel的实现控制着什么(如果有的话)被写回到您的模型。

除非模型也是ViewModel(即您没有“模型”),否则INotifyPropertyChanged (INPC) 永远不应在模型中。 INPC只能出现在视图模型中。

该模型应该对视图模型一无所知,因此永远无法与其进行通信。 只有视图模型可以与模型通信。

从UI的角度来看,只有视图模型才能对数据执行任何操作; 因此,如果您希望模型是“只读的”,那么就不要在视图模型中实现它。

绑定将使用视图模型完成,在这种情况下,请不要使用Dictionary(除非您想编写代码将其包装以便绑定它)。 如果Dictionary在模型中,那么您应该在视图模型中“包装”它-在集合周围编写一个可观察的包装器是很简单的。 您的视图模型极有可能不会处理键/值对-它应该处理的是UI可以处理(并绑定到)的平面对象。

更新
引入INPC进行数据绑定。 它将视图与特定的具体类解耦,因此只需要了解INPC(注意解耦的方向)。 就MVVM而言,这将视图与视图模型分离,在PM的情况下,可将视图与演示者分离,在MVC的情况下,这可将视图与控制器分离,在MVP的情况下,将视图与控制器分离。演示者的观点。

数据绑定是一种将数据绑定到UI元素的技术。 它将数据源绑定到目标,以便目标可以请求数据,无论它认为合适如何,或者源可以推送数据但认为合适(取决于绑定的类型 ,它可以是单向或静态的,从而限制了经常会发生/推送)。

有时,数据源与目标之间的分离关系的必要性质使人们认为数据绑定不是UI问题,并且数据绑定可以应用于任何地方。 也就是说,数据绑定实现与UI完全分离。 通常这是一个错误。 数据绑定将视图与特定类的特定知识分离开来(这是基本分层和避免循环,我在这里不介绍)。 但是,它并不能完全将视图与数据源分离。 没有数据源就无法进行绑定-那里仍然有一定程度的耦合,只是缓解了编译时耦合(测试辅助,灵活性,健壮性等,但必须在生产时的运行时提供) ,例如可以测试INPC实现而无需在运行时将其绑定到UI元素这一事实,并不意味着它不依赖于UI框架。 视图仍然松散地耦合到数据源这一事实并不是这种关系中的唯一耦合。 数据源通过其UI框架松散地(如果不太松散 )耦合视图。

每个UI框架都有一个限制,即必须在主线程或UI线程上完成对UI元素的访问和修改。 (至少在Windows上;它可能在其他平台上发生,我只是不精通任何其他平台)。 使用数据绑定,源将间接绑定到控件,并且任何数据更改都会直接更改一个或多个UI元素(取决于您可以使用中介的框架。类似于WinRT中的值转换器 ,但它们的职责是转换或转换数据)。 这意味着数据源需要有深入的了解,它绑定到UI和什么类型的UI框架,它是结合的。 与UI框架的这种紧密耦合清楚地将数据源(仍然很松散)耦合到了UI。

这意味着INPC的任何特定实现实际上都绑定到一个并且只有一个UI框架。 该对象不再可以在任何地方使用(显然, 在任何地方都是理想的选择,对于每种情况都无法使任何东西正常工作-这里的重点是在不止一种或两种情况下的高凝聚力)。 例如,如果在多线程环境中使用INPC的实现,则它需要在发送属性通知之前将数据“封送”回UI线程。 在WinForms中,这是Control.BeginInvoke ,在WPF和Silverlight中是通过System.Windows.Threading.Dispatcher 在WinRT中,这是通过Windows.UI.CoreDispatcher 在所有情况下,INPC实现都必须直接耦合到一个UI框架。 在Silverlight的情况下,这直接耦合到“桌面” Dispatcher或Windows Phone Dispatcher

质量指标包括凝聚力等概念。 内聚性是两个代码单元之间紧密相关程度的度量。 由于支持一个特定的UI框架所需的所有基础结构的性质,尽管可能能够在UI之外使用,但由于UI以外的其他事物所使用的INPC的实现将具有较低的内聚性,因为所有与UI框架相关的代码将不被使用。 也就是说,要承担与UI完全脱钩的责任。 是的,您可以在任何地方使用实现INPC的对象,而从不使用PropertyChanged事件,但是您的理解力很低(被认为是不好的)。

如果我在模型中实现了INPC,并且想同时在UI和WCF或Web服务后端中使用该模型,那么我要么不能,要么后端必须参考一些UI框架。 如果我想在另一种类型的UI中使用该模型,则不会,因为INPC的实现取决于一个特定的UI框架。 我不得不写另一个“模型”。 这时显然是“视图模型”。

INPC本身不绑定到特定的UI框架(也不应该)。 这导致人们误以为INPC可以在任何地方使用。 是的 ,它缺乏与高级名称空间的耦合意味着可以使用 ,但是INPC的压倒性用途是当目标是UI时。 我会挑战INPC的任何其他用法,这些用法不将UI视为真正的“绑定”。 与其他任何工具一样,您可以滥用它来获得有用的结果。 INPC 用于投影数据,也可用于转换数据等。 但我相信这些是对INPC的滥用,而且确实超出了此问题的范围...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM