如何在MVVM架构中实现Model和ViewModel的双向同步?

4

这是一个简单的问题,我在网上搜索了几个小时也没有找到答案...

我有一个模型和一个视图模型,其中包含一个属性。为了在视图中查看此属性,我使用一个视图模型对象,该对象应自动从模型对象生成,并反之亦然。当然,以下代码将引发StackOverflowException异常,因为在模型中更新模型对象会导致在视图模型中更新视图模型对象,这又会导致在模型中更新模型对象,以此类推...

class ModelObject
{
  ...
}

class ViewModelObject
{
  ...
}

class Model : INotifyPropertyChanged
{
  private ModelObject modelObject = new ModelObject();

  ...

  public ModelObject ModelObject
  {
    get
    {
      return this.modelObject;
    }
    set
    {
      this.modelObject = value;
      this.NotifyPropertyChanged("ModelObject");
    }
  }
}

class ViewModel : INotifyPropertyChanged
{
  private ViewModelObject viewModelObject = new ViewModelObject();
  private Model model = new Model();

  ...

  public ViewModel()
  {
    this.model.PropertyChanged += new PropertyChangedEventHandler(this.propertyChangedEvent);
  }

  public ViewModelObject ViewModelObject
  {
    get
    {
      return this.viewModelObject;
    }
    set
    {
      this.viewModelObject = value;
      this.model.ModelObject = new ModelObject(...);
      this.NotifyPropertyChanged("ViewModelObject");
    }
  }

  private void propertyChangedEvent(object sender, PropertyChangedEventArgs e)
  {
    if (e.PropertyName.Equals("ModelObject"))
    {
      this.ViewModelObject = new ViewModelObject(...);
    }
  }
}

什么是同步这两个对象的常见方式?

这种行为的应用是什么?你在哪里使用它?你想要做什么? - Floremin
我认为在MVVM中,同步视图模型和模型是基本的。我需要在不同情况下始终保持这种行为。 - Stephan Engelhardt
1个回答

5

没有银弹。模型是数据库的表示,而视图模型更接近界面,因此始终需要一些业务逻辑将模型转换为视图模型,反之亦然。

我的视图模型类通常有两种方法 - SyncModel(ViewModel viewModel)SyncViewModel(Model model)

还有一个建议 - 模型不应实现 INotifyPropertyChanged 接口。视图模型应该实现这个接口,因为它与用户界面绑定。为什么模型需要改变呢?它代表了数据库中的内容。您可以刷新它,但为什么需要为模型提供更改通知呢?

编辑: MVVM: Binding to Model while keeping Model in sync with a server version

硬引用。每个类都拥有对另一个类的引用,监听属性更改事件并相应地更新自己。

观察者模式 - 有一个观察者类,每个类向观察者注册自己,观察者监听任何更改并更新其所有订阅者。

还有一个事件聚合器可能会有用。

如果您想要延迟更新,那么需要一个 isDirty 属性。您更了解自己的应用程序,可以搜索更多文章并明智地选择。


3
我在示例中提到的模型并不代表数据库,它只是内存中的一个简单模型。因此,该模型也可以通过另一个视图模型进行更改,而上面的视图模型应该被告知以触发INotifyPropertyChanged事件,这将导致界面刷新。 - Stephan Engelhardt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接