c# - MVVM:绑定(bind)到模型,同时使模型与服务器版本保持同步

标签 c# silverlight mvvm domain-driven-design prism

我花了很多时间尝试为以下挑战找到一种优雅的解决方案。我一直无法找到解决问题的方法,而不仅仅是解决该问题。

我有一个简单的View,ViewModel和Model设置。为了说明起见,我将使其非常简单。

  • Model具有一个名为Title的字符串类型的单个属性。
  • ModelView的DataContext。
  • ViewTextBlock数据绑定(bind)到模型上的Title
  • ViewModel具有一种称为Save()的方法,该方法会将Model保存为Server
  • Server可以推送对Model所做的更改

  • 到目前为止,一切都很好。现在,我需要进行两项调整,以使模型与Server保持同步。服务器的类型并不重要。只是知道我需要调用Save()才能将模型推送到Server.
    调整1:
  • Model.Title属性将需要调用RaisePropertyChanged(),以便将ModelServer所做的更改转换为View。这很好用,因为ModelView的DataContext

  • 还不错

    调整2:
  • 下一步是调用Save(),将对View所做的更改保存到Model上的Server中。这就是我卡住的地方。我可以处理在更改模型时调用Save()的Model.PropertyChanged上的ViewModel事件,但这会使它回显服务器所做的更改。

  • 我正在寻找一种优雅且合乎逻辑的解决方案,并愿意在合理的情况下更改我的体系结构。

    最佳答案

    过去,我编写了一个应用程序,该应用程序支持从多个位置“实时”编辑数据对象:该应用程序的许多实例可以同时编辑同一对象,并且当有人将更改推送到服务器时,其他人都会收到通知, (在最简单的情况下)立即看到这些更改。这是它的设计摘要。
    设置

  • View 始终绑定(bind)到ViewModels。我知道这是很多样板,但是除了最简单的情况外,直接绑定(bind)到模型是 Not Acceptable 。这也不符合MVVM的精神。
  • ViewModels负责插入更改。显然,这包括将更改推送到服务器,但也可能包括将更改推送到应用程序的其他组件。
    为此,ViewModels可能希望克隆它们包装的模型,以便它们可以在向服务器提供服务时为应用程序的其余部分提供事务语义(即,您可以选择何时将更改推送到应用程序的其余部分,您可以如果每个人都直接绑定(bind)到同一Model实例,则无法执行此操作)。隔离这样的更改还需要做更多的工作,但同时也带来了强大的可能性(例如,撤消更改是微不足道的:只是不要插入更改)。
  • ViewModels对某种数据服务有依赖性。数据服务是一个应用程序组件,位于数据存储区和使用者之间,并处理它们之间的所有通信。每当ViewModel克隆其Model时,它也会订阅数据服务公开的相应“数据存储已更改”事件。
    这样,就可以将其他ViewModel已推送到数据存储并对其做出适当 react 的“其”模型更改通知给ViewModel。通过适当的抽象,数据存储也可以是任何东西(例如,该特定应用程序中的WCF服务)。

  • 工作流程
  • 创建ViewModel并为其分配模型所有权。它立即克隆模型,并将此克隆公开给 View 。依赖于数据服务,它告诉DS它希望订阅通知以更新此特定模型。 ViewModel不知道它是什么,它可以标识其模型(“主键”),但是不需要这样做,因为这是DS的责任。
  • 用户完成编辑后,他们将与 View 交互,该 View 将调用VM上的命令。然后,VM调用DS,推送对其克隆的Model所做的更改。
  • DS会保留更改,并另外引发一个事件,通知所有其他感兴趣的VM已对Model X进行了更改。新版本的Model作为事件参数的一部分提供。
  • 现在,已被分配了同一模型所有权的其他VM知道外部更改已到。现在,他们可以决定如何更新具有所有难题的 View (已克隆模型的“先前”版本;已克隆的“肮脏”版本;以及已发行难题的“当前”版本)。被推送为事件参数的一部分)。

  • 笔记
  • 模型的INotifyPropertyChanged仅由View使用;如果ViewModel想知道Model是否为“脏”,它可以始终将克隆与原始版本进行比较(如果保留了该克隆,我建议尽可能这样做)。
  • ViewModel原子地将更改推送到服务器,这很好,因为它确保数据存储始终处于一致状态。这是一种设计选择,如果您想以不同的方式做事,则另一种设计会更合适。
  • 如果ViewModel将this作为参数传递给“push changes”调用,则服务器可以选择不引发负责此更改的ViewModel的“模型更改”事件。即使没有,如果ViewModel看到Model的“当前”版本与其自己的克隆相同,则可以选择不执行任何操作。
  • 有了足够的抽象,更改就可以轻松推送到在其他计算机上运行的其他进程,就像轻松推送到Shell中的其他 View 一样。

  • 希望这可以帮助;如果需要,我可以提供更多说明。

    关于c# - MVVM:绑定(bind)到模型,同时使模型与服务器版本保持同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10437241/

    相关文章:

    swift - 带有 RxSwift 的 MVVM-C : '[weak self]' in closure

    c# - 用户控制按钮绑定(bind)不响应主视图模型上的中继命令

    c# - 更快地读取文件并快速获取像素颜色?

    silverlight - Silverlight 根标记应该是 UserControl 还是 Canvas?

    c# - Expression Blend 示例数据和数据模板

    wcf - Azure 上的 WCF 使用了哪种类型的安全性且与 Silverlight 兼容?

    c# - 如何正确使用列表框项目模板/数据模板中的按钮?

    c# - View 未在区域中显示

    c# - 仅打印嵌入到 ASP.NET 页面中的图像

    c# - Count是否实现了一个IEnumerable