2

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

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

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

4

5 回答 5

5

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

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

  • 如果模型的状态修改方法被记录为同步执行,则在 ViewModel 上创建将操作转发给模型的方法,然后立即查询其状态。使用这些方法来实现RelayCommands。
  • 如果模型的方法不是同步的,那么模型的客户端应该有一些机制可以在方法完成时通知他们。这可以通过延续回调、事件或者甚至使用INotifyPropertyChanged.
于 2012-11-27T09:50:58.210 回答
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");
   }
}
于 2012-11-27T09:55:58.027 回答
3

您可以在 ViewModel 对 Model 执行方法之后调用 OnNotifyPropertyChanged。这不是很优雅,但是如果不重构 Model 类,您将无法变得更简单。

于 2012-11-27T09:54:30.273 回答
1

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

于 2012-11-27T09:49:45.527 回答
1

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

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

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

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

于 2012-11-27T09:57:05.760 回答