2012-11-27 42 views
2

這是關於MVVM模式最佳實踐的特定問題。我正在使用MvvmLight庫。 它是這樣的: 我的模型,比如說「飛行」,實現了一些業務邏輯,可以通過方法啓動,暫停和停止航班。每種方法都有自己的邏輯,無論是在停止還是暫停飛行,都會發揮功能。變化的一個重要變量是指示航班狀態的狀態枚舉 - 播放,停止或暫停。如上所述,狀態變量(和屬性)在模型中定義。 另一方面,飛行類由包含狀態屬性的ViewModel類包裹,該狀態屬性將狀態變量包裹在飛行模型中,並且連接到飛行模型的RelayCommands也會播放停止暫停方法。MVVM:模型狀態改變時通知視圖

這裏的問題開始於: 當我通過視圖執行其中一個命令時,它執行模型中的方法,以便狀態變量本身直接改變,但它只在模型中改變。 ViewModel並不知道包裝變量是否已被更改,因爲它已被直接更改......這意味着如果某些視圖元素綁定到狀態屬性,則在執行命令時它不會更改。

I知道幾種方法來解決這個問題,但我要求一個公平的解決方案,不會打破MVVM模式(如在模型中的飛行類中使用INotifyPropertyChanged)

回答

5

對於此類問題沒有靈丹妙藥解決方案。您的ViewModel和Model需要以允許信息傳播到View的方式進行設計;如果這是不可能的,那麼設計是有缺陷的,需要改變。

這裏有幾件事情你應該看看:

  • 如果模型的狀態改良方法都記錄同步執行,創建視圖模型是向前的動作示範的方法,然後立即查詢其州。使用這些方法來實施RelayCommand
  • 如果模型的方法不同步,那麼應該有一些機制可供模型的客戶端在方法完成時通知他們。這可以通過連續回調,事件或甚至通過INotifyPropertyChanged來完成。
1

最佳做法是從命令執行調用viewmodel,而不是從視圖模型更改視圖模型,之後標記視圖模型狀態爲已更改

+0

如果模型無法更改會發生什麼,例如如果拋出異常? – Jon

+1

比ViewModel失敗,你認爲這是一個問題嗎? –

+0

我不確定「ViewModel失敗」是什麼意思。我按Play,VM狀態改變爲「正在播放」,調用Model.Play(),然後拋出。 VM現在的狀態是什麼? – Jon

3

您可以在ViewModel在Model上執行該方法後立即調用OnNotifyPropertyChanged。這不是很優雅,但是如果不重構Model類,你就不會變得更簡單。

4

正如您上面提到的,您的視圖模型應在下列方式包裝型號:

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"); 
    } 
} 
+3

基本上這就是我剛纔寫的:) –

1

你知道執行命令後,什麼樣的屬性有哪些變化?我的意思是,您是否可以明確提出關於特定屬性集的更改通知,或者修改的屬性集是否正在更改?

在前一種情況下,你調用命令,並明確提高這些屬性的事件:使用反射

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

在第二種情況下,你可以提高更改通知事件爲Model類的每一個屬性或者您也可以使用更智能的解決方案,如PostSharp.Domain.Toolkit

相關問題