2012-02-09 76 views
1

我有一個架構問題,以及我想要一個意見的可能解決方案。我習慣了WP7的MVVM體系結構(只要有可能,但不幸的是,有時sdk似乎走向相反的方向)。ViewModel事件註冊和ViewModel生命週期

WP7強制使用ViewFirst方法,我覺得這很適合(除了我們無法重寫視圖創建的部分,就像在Silverlight中,使構造函數注入成爲可能)。 我發現自己很有信心,因爲大部分視圖模型都遵循其視圖的lyfetime。所以viewmodel是在創建視圖時創建的(通過訪問ViewModelLocator),ViewModel是(或者應該)只能被其視圖引用,當視圖被銷燬時,它的ViewModel也應該被銷燬(它不是強制性的,而是它的方式我去除非常罕見的情況下,我創建一個singleton viewmodel)。

我的viewmodel可能需要註冊一些單例服務事件(我創建的phoneservice或singleton類)。我的意思是,它可能需要註冊一個類,該類的生命週期不是由視圖模型本身決定的。 這些事件對我的viewmodel保持了一個硬引用,並且即使視圖被刪除,我的viewmodel也仍然存在,不僅如此,我的viewmodel將繼續接收和處理這些事件。 WeakEvent模式可能是一種可能的解決方案,但對於爲每個事件創建事件管理器都是不可取的。在我看來,最好的解決方案並不存在,並且應該成爲弱事件註冊的關鍵詞。

我找到的解決方案是讓我的viewmodel知道NavigateTo和NavigateFrom,所以我可以從那裏註冊和取消註冊事件。我還可以添加一些邏輯(例如,我只能在註銷的情況下取消註冊),注意在NavigateTo和NavigateFrom中有高光邏輯。

另一種可能的方式(我還沒有測試過)可能會讓我的viewmodel意識到視圖定型並在視圖完成時執行一些清理,但我總是有這種感覺,因爲這種方法並不被推薦使用,定稿。此外,我不清楚性能會受到多大影響。

您如何看待viewmodel生命週期與其視圖相同(它總是簡化我的應用程序直到現在)? 您如何看待NavigateTo-Navigate從ViewModel感知解決方案? 您對View-Finalization ViewModel感知解決方案有什麼看法? 您是否遇到過這些或其他類型的解決方案?

問候 SkyG

UPDATE

我發現,最終確定的解決方案不會做的工作怎麼一回事,因爲它可以發生在未來的後期(也許永遠不會)。 現在看來我認爲最好的解決方案是viewmodelbase中的一對虛擬方法,用於初始化和清理視圖應該調用的事件註冊註銷。 可能會調用它們的時刻可能是在加載和卸載事件期間(當我不需要我的viewmodel處理事件時,如果我處於後續視圖中,在這種情況下,第一個視圖/ viewmodel仍然在後臺存活但如果它們的視圖被連接/分離到可視化樹上,則會加載/卸載)。

任何其他意見(甚至confermative)將不勝感激。

謝謝

回答

1

,你有什麼看法具有視圖模型的壽命是一樣的 視圖(它總是簡化我的應用程序到現在爲止)?

這對我來說聽起來很合理,因爲它與視圖的DataContext直接相關。

您如何看待NavigateTo-Navigate從ViewModel知道 解決方案?

我不認爲這是一個好主意。在MVVM模式中,ViewModels應該對視圖一無所知。導航通常與觀點相關,所以我不認爲這是最好的主意。

您如何看待定型ViewModel感知解決方案 ?

沒有具體談論定稿,視圖模型的清理方法是IMO的路要走。在您所有的ViewModels的基類(我希望你有一個),你可以把下面的方法:

public abstract class ViewModelBase 
{ 
    .... 
    public virtual void Cleanup(); 
} 

然後,只需撥打myViewModel.CleanUp();當你的視圖被關閉。 取消註冊事件的具體實施CleanUp

public override void CleanUp() 
{ 
    ....Event -= this....EventHandler; 
} 
+0

我同意ViewModel不應該是viewaware,但我打算它不應該是特定的viewaware。我可以讓ViewModel知道導航而不知道視圖(例如使用Messenger)。有沒有其他技術上的原因,你不喜歡這種方法?對於清理它聽起來不錯,唯一的問題是什麼時候調用它,並且我只能想到在導航過程中調用它仍然與上面相同或在定稿期間,你有任何其他想法? – SkyG 2012-02-09 17:38:03

+0

我也發現定稿不會奏效,因爲它可能會在未來發生。視圖模型庫中的虛擬清理是最好的解決方案(所以視圖只會瞭解基礎)。我必須弄清楚什麼時候是最好的時機。在大多數情況下,Unloaded事件可能是唯一的(記住,視圖從視覺樹中分離的所有時間都被稱爲視圖,但視圖可以在後臺堆棧中繼續存在)。在這種情況下,事件註冊應該在加載的事件中發生,所以我需要添加一個Initialize方法到viewmodel基礎。 – SkyG 2012-02-10 12:35:45

1

我同意弱事件的想法是好的,但它會太麻煩來實現。它也創造了它自己的問題 - 它可以使viewmodel完全弱引用,使它在實際「應該」之前成爲垃圾收集方式的候選者(開發者意見vs垃圾回收者意見)。之前我已經被Ward Bell咬過了,這個blog post of his

根據您的要求和渴望遵循MVVM的「純粹」方法(viewmodel不知道視圖),似乎您正在努力平衡「視圖」和「模型」之間的平衡視圖模型。在這種情況下,我實際上會提出另一種設計模式:MVPVM(model/view/presenter/viewmodel)。這裏有一個MSDN article

就你而言,主持人將堅持這些單身事件。主持人瞭解視圖是可以的,因爲主持人並不意味着在視圖之間重複使用。然後,您的視圖模型將成爲「視圖模型」,允許重複使用並消除大多數生命週期問題。

我喜歡MVPVM方法,因爲當我的視圖模型開始承擔太多責任時,它始終關注我MVVM(與數據訪問層交談,監聽應用程序範圍內的事件以及處理來自視圖的命令,維護其視圖的屬性等)。我知道這不一定是你的問題的答案,但對於評論太長了。