2010-12-15 56 views
0

嗨 我想知道,如果這種做法是正確的,或者是什麼應該是一個 我有一個MVVM模式的權利,我有一個ListView 我的想法是,當我選擇列表視圖中的項目,視圖模型中的屬性會使用選定的對象進行更新。 HOwever,當用戶按下Intro時,我希望viewmodel做些事情(打開一個新的瀏覽器窗口)。我做了這樣的事情:需要調用視圖模型的方法從View

private void listView1_KeyDown(object sender, System.Windows.Input.KeyEventArgs e) 
     { 
      var vm = Resources["Locator"] as MainViewModel; 

      if (listView1.SelectedIndex != -1 && e.Key == Key.Enter) 
      { 
       vm.OpenBrowserForSelectedOffer(); 
      } 
     } 

但是我不知道這是不是有事情好做,或者別的東西應該做的正確途徑。因爲在這種情況下,視圖實際上是在請求視圖模型(這是一種資源),也許它「知道太多」,並且有更好的實踐來解決這類問題。

回答

2

OpenBrowserForOffer的作用並不完全清楚,但我猜測它會爲該報價打開一個新的瀏覽器窗口(例如使用Process.Start()),對吧?

如果是這樣的話,我認爲這是完全可以的視圖模型來處理這一點,因爲它的業務邏輯的一部分。

視圖沒有問題知道或假設有關視圖模型的東西,它已經做到了(因爲你綁定到它的屬性)。

正如在另一個答案中所建議的,您可以通過查看DataContext輕鬆獲取您的視圖的當前視圖模型。在需要代碼訪問視圖模型的視圖中,爲了方便,我通常實現兩個屬性:

private YourViewModelType ViewModel 
{ 
    get { return DataContext as YourViewModelType; } 
} 

private bool HasViewModel { get { return ViewModel != null; } } 
+0

打開瀏覽器是UI邏輯,而不是業務邏輯;並在視圖模型中加入類似的東西使其無法測試。 – 2010-12-15 14:27:44

+0

可測試性可以被解決(就像你在你的答案中提出的那樣),我不同意僅僅因爲它恰好啓動了一個具有UI的外部程序,它就是UI邏輯。 – 2010-12-15 15:25:32

+0

在視圖模型中使用Process.Start對我來說不是一個好方法,因爲你不能嘲笑它。但是可能我們說的是同樣的東西:處理本身是在視圖模型中完成的,但是Process.Start的實際實現應該被抽象出來。 – 2010-12-15 15:34:48

1

在綁定到ListView的KeyDown-Event/Command的Viewmodel中使用命令,並在viewmodel中的命令中移動代碼,voilá,您清除了mvvm模式。

3

我假定您使用的是WPF或Silverlight。使用命令模式當然是執行由UI事件觸發的命令的正確方式。但問題是,在你的情況下,這個操作本身對UI做了一些事情;這不是視圖模型的責任。

它可以用簡單的方法解決,以便視圖模型保持可測試性。使用OpenBrowserForOffer操作創建一個IBrowserService接口。

public void OpenBrowserForOffer(Offer offer, Action<Result> callback) 

創建一個實現它打開瀏覽器並顯示選定的報價。創建另一個實現,它是一個沒有UI內容的模擬實現。

然後從視圖模型注入一個IBrowserService實例,並使用它打開瀏覽器或執行模擬邏輯,具體取決於從實際應用程序或測試運行。

請注意,在視圖中您可以使用DataContext來獲取視圖模型。

+0

這是一個很好的做法,所以我會給你一個「up」。然而,在這種特殊情況下,它並不真正與視圖進行交互(視圖只是說「做這個」,並且不期望任何回報)。 – 2010-12-15 14:27:33

+0

但'做這個'是與UI交互,不是嗎?所以你的viewmodel與UI交互? – 2010-12-15 14:34:06

+0

取決於你的意思是通過交互.. 具體的情況是,我有一個列表視圖中包含項目,並且這些項目的屬性之一是一個url。當你點擊INTRO時,應該打開一個帶有該URL的新瀏覽器窗口。沒有更多 – 2010-12-15 21:57:50