2012-08-10 67 views
1

我在我的WPF應用程序中使用MVVM模式。我試圖緩存我的窗戶,以提高性能。要做到這一點,我絕不會關閉它們,只是隱藏而不是關閉。所有隱藏的窗口都存儲在字典中,所以我可以重新使用它們。當窗口再次打開時,我創建一個新的視圖模型並將其與緩存視圖關聯。不要從隱藏窗口調用CanExecute方法

但有一個問題,因爲隱藏的窗口不斷調用ViewModels中的CanExecute命令方法。當用戶打開和關閉很多窗口時,這會導致性能問題。

當我將Window.DataContext屬性設置爲null或執行ClearValue(DataContextProperty)我實現了我的目標,但是存在問題。如果我有任何雙向綁定,它們在從數據上下文解除綁定期間都會觸發。所以,我的視圖模型中的一些值變爲null。我不希望這樣做,因爲在某些情況下,我會在隱藏Views之後從ViewModel讀取屬性。

你能幫我解決主要問題(不要從隱藏的窗口調用CanExecute方法)。

+0

您是使用RoutedCommands還是您自己的自定義ICommand實現? – mclark1129 2012-08-10 16:13:32

+1

您沒有正確使用您的虛擬機。當一個視圖關閉(隱藏)時,(最終)VM被拋出。您應該重構代碼,不要引用「隱藏」的虛擬機。在發生未綁定之前,先做任何你需要做的事情,然後立即處理它。不要將您的緩存視圖視爲隱藏,將它們視爲已關閉,因爲這就是它們的實際情況。 – 2012-08-10 16:48:03

回答

2

我不認爲你對CommandManager何時何地決定觸發RequerySuggested事件沒有太大控制。您可能能夠減輕性能影響的一種方法是在ViewModel上擁有一個屬性,允許您執行CanExecute。每當一種觀點認爲一個視圖模型勢必進入隱藏,那麼你可以將此屬性設置爲

一個簡單的例子

// Called when a view goes into hiding 
myViewModel.SuppressCommandRequery = True 

在你CanExecute處理程序(一個或多個)只需把此行在方法的開始

public bool CanExecuteCommand(Object parameter) { 

    if (this.SuppressCommandRequery) 
     return; 

    // Continue processing the event... 
} 

我會指出,你需要特別小心,然後禁用每當視圖出來隱藏抑制。但是,在將視圖結果重新顯示在ViewModel的新實例中的情況下,這不是必需的。

或者,看看this question,其中討論了使用Prism MVVM框架中的DeletegateCommand的實現。我自己並沒有使用過它,但它看起來可能會解決您的一些擔憂。

+1

我不確定爲什麼人們將他們的命令掛接到CommandManager中。我想,它的一些崇拜貨物的程序開始於一些ICommand實現的最早例子。人,如果你不知道你*需要*做到這一點,那麼不要!我已經創建了數百個命令,而不需要將它們掛接到CommandManager,並且從來沒有錯過它。 – Will 2012-08-10 16:53:41

+1

你可能是對的。我認爲CommandManager真正成爲必需的唯一時間是當你的Command的執行能力依賴於UI中的某些東西(比如鼠標的位置)時。在這種情況下,命令可能不會真正在您的ViewModel上,而不會違反MVVM。 – mclark1129 2012-08-10 17:18:27

+0

謝謝,我會按照你的意見,並添加一個屬性到我的視圖模型。我有我的視圖模型和視圖的基類,所以,鉤住隱藏事件很容易。另外,爲了在調用CanExecute方法之前檢查該屬性,我將更改我的命令的基類的實現。 – Egor4eg 2012-08-13 09:10:50