MVVM:模型状态更改时通知视图

时间:2012-11-27 09:43:19

标签: wpf mvvm mvvm-light

这是关于MVVM模式最佳实践的特定问题。我正在使用MvvmLight库。 它是这样的: 我的模型,说“飞行”,实现了一些业务逻辑,可以通过方法启动,暂停和停止飞行。无论是停止还是暂停飞行,每种方法都会使其功能发生。一个重要的变量是状态枚举,表示航班状态 - 播放,停止或暂停。如上所述,状态变量(和属性)在模型中定义。  另一方面,航班类由一个ViewModel类包装,该类包含一个包裹飞行模型中状态变量的Status属性,以及连接到飞行模型播放停止暂停方法的RelayCommands。

问题在于: 当我通过视图执行其中一个命令时,它会执行模型中的方法,以便状态变量本身直接更改,但它只会在模型中更改.ViewModel中的status属性不知道包装的变量已被更改,因为它已直接更改...这意味着如果某个视图元素绑定到status属性,它将不会在命令执行时更改..

我知道有几种方法可以解决这个问题,但我要求一个不会破坏MVVM模式的公平解决方案(比如在模型的飞行课中使用INotifyPropertyChanged)

5 个答案:

答案 0 :(得分:5)

这类问题没有灵丹妙药解决方案。您的ViewModel和Model需要以允许信息传播到View的方式进行设计;如果这是不可能的,那么设计是有缺陷的,需要改变。

以下是您应该研究的几件事:

  • 如果记录模型的状态修改方法以同步执行,则在ViewModel上创建方法,将方法转发给模型,然后立即查询其状态。使用这些方法来实现RelayCommand s。
  • 如果Model的方法不同步,那么Model的客户端应该有一些机制可以在方法完成时通知它们。这可以通过延续回调,事件,甚至是INotifyPropertyChanged来完成。

答案 1 :(得分:4)

如上所述,您的ViewModel应按以下方式包装Model:

class Model
{
   public int State{get;private set;}
   public void Fly()
   {
      State=1;
   }

   public void Stop()
   {
      State = 2;
   }
}

class ViewModel : ViewModelBase
{
   int State{ get{ Model.State;}}
   ...
   OnFlyCommand()
   {
      Model.Fly();
      NotifyPropertyChanged("State");
   }
}

答案 2 :(得分:3)

您可以在ViewModel在Model上执行方法后立即调用OnNotifyPropertyChanged。这不是很优雅,但如果不重构你的Model类,你就不会变得更简单。

答案 3 :(得分:1)

最佳做法是从命令执行调用viewmodel,而不是从viewmodel调用模型更改,之后将viewmodel状态标记为已更改

答案 4 :(得分:1)

执行命令后,您知道哪些属性已更改?我的意思是,您是否可以明确提出特定属性集的更改通知,或者修改后的属性集正在发生变化?

在前一种情况下,您可以调用命令并显式提升这些属性的事件:

command.Execute();
NotifyPropertyChanged("PropA");
...
NotifyPropertyChanged("PropN");

在第二种情况下,您可以使用反射为Model类的每个属性引发更改通知事件,或者您可以使用更智能的解决方案,如PostSharp.Domain.Toolkit