2013-05-08 43 views
1

我正在使用MVVM模式(使用MVVM Light)構建我的XAML應用程序(win8)。我有一個ListView,它綁定到我的ViewModel的屬性。我也有一個按鈕觸發該ViewModel的操作,該操作更新該屬性(這會導致更新ListView)。該按鈕使用命令在ViewModel上執行操作。到現在爲止還挺好。MVVM模式 - 執行視圖操作

問題是,在刷新列表後,我需要執行嚴格屬於我的視圖的操作,而不是ViewModel。它應該將列表滾動到特定項目。如何觸發該操作?我應該使用特定的ListView事件嗎?

回答

1

使用EventHandlerScrollIntoView(Object)方法,您可以在不使用ViewMovel內部視圖的引用並且尊重MVVM模式的情況下實現自己想要的功能。

在您的視圖模型像這樣創建一個事件:

public event EventHandler ScrollListView; 

在您的視圖中添加一個回調滾動ListView當屬性更新:

ViewModel vm; 
vm.ScrollListView += (sender, e) => 
{ 
    var specificItem = **some item**; 
    MyListView.SelectedItem = specificItem; 
    MyListView.UpdateLayout(); 
    MyListView.ScrollIntoView(MyListView.SelectedItem); 
}; 

然後在您的視圖模型,當你更新該財產,並希望滾動ListView

if (this.ScrollListView != null) 
{ 
    this.ScrollListView(this, EventArgs.Empty); 
} 

這就是我通常對每種情況做一些調整的過程。

1

ViewModel用於將UI代碼與UI設計(例如XAML)分離。 [分離設計師和開發人員的關注,UI代碼的自動化測試等]

理想情況下,視圖的代碼隱藏文件將爲空(除了調用InitializeComponent)並且所有UI邏輯和狀態都將由ViewModel。但是,在實踐中,可能會有一些特定的UI操作無法單獨由數據綁定來處理,因此您需要使用代碼。這樣的代碼應該放在代碼隱藏中。

在你的情況下,(a)when和(b)要滾動到哪個項目的邏輯必須在ViewModel中(不在視圖中)。只有在ListView中執行實際滾動所需的任何附加邏輯纔會出現在View代碼隱藏中。

是的,一個事件將是完成此操作的理想方法,以避免對ViewModel中的視圖進行任何引用。然而,我會建議在ViewModel中創建一個自定義事件(例如OnFirstItemInViewChanged,參數要滾動到的項目),並在View代碼隱藏中註冊到此事件,並調用ListView.ScrollIntoView(item)。

說明: WinForms DataGridView有一個屬性FirstDisplayedScrollingRowIndex。如果在WPF ListView中有類似的東西,你可以通過將這個屬性綁定到一個ViewModel屬性來解決這個問題,因此讓代碼保持完全乾淨。