2009-02-17 19 views
5

單行摘要:在Silverlight2的UserControl的構造函數中創建的解除鉤接事件處理程序的最佳做法是什麼?何時在Silverlight中解除事件

背景: 我目前正在Silverlight2中構建一個業務線應用程序。由於Silverlight是一個瀏覽器插件,因此沒有Window的概念 - 所有內容都在UserControls內完成。我在應用程序中處理不同「表單」的方式是擁有一個包含Viewbox的頂級用戶控件。爲了顯示不同的形式,我將Viewbox的Child屬性設置爲不同的UserControl。我的應用程序有一個單獨的PageManager類,它被調用來打開和關閉表單。窗體(UserControls)存儲在一個堆棧中。打開表單將其放在堆棧的頂部,關閉它將其從堆棧中移除並顯示其下面的一個。

我試圖按照Model-View-ViewModel模式。在每個表單(從UserControl派生)中,我有一個ViewModel來管理View的所有數據。 ViewModel公開事件,以便在加載和保存等操作完成時通知UI。

在我的形式,我同意在構造函數中的事件,我已經得到了視圖模型

public partial class MyPage : UserControl 
{ 

    public MyViewModel ViewModel{get; set;} 

    // other constructors, which create the viewmodel and call the constructor below. 

    public MyPage(MyViewModel viewModel) 
    { 
     InitializeComponent(); 
     ViewModel = viewModel; 
     this.LayoutRoot.DataContext = this.ViewModel; 

     // subscribe to event so we can do stuff 
     this.ViewModel.LoadCompleted += new MyViewModel.LoadCompletedEventHandler(ViewModel_LoadCompleted); 
    } 

我的問題是後:現在我已經訂閱了這個事件,我什麼時候刪除處理程序?我是否創建了一個析構函數並在那裏執行,或者是否創建了雞與雞蛋的情況:垃圾收集器在所有引用(即:事件處理程序)都不存在之前不會銷燬該對象?我是否創建一個表單必須實現的接口,該接口指定當PageManager關閉表單時調用的UnhookEvents函數?

編輯:謝謝你的迴應。什麼情況下ViewModel的持續時間比表單(UserControl)更長?我的部分應用程序允許用戶創建相當複雜的結構,但在95%的情況下,它更簡單。我所做的是創建2個使用相同ViewModel的表單。用戶可以開始填寫簡單表單,然後切換到高級模式,這會創建一個新表單,並將ViewModel傳遞給它。

在簡單的設置形式:

private void AdvancedSessionSetupButton_Click(object sender, RoutedEventArgs e) 
    { 
     PageManager.GetPageManager().Close(this); 
     PageManager.GetPageManager().Open(new CreateSessionPage(this.ViewModel), "Create Session"); 
    } 

在高級設置形式:

private void BasicSessionSetupButton_Click(object sender, RoutedEventArgs e) 
    { 
     PageManager.GetPageManager().Close(this); 
     PageManager.GetPageManager().Open(new CreateBasicSessionPage(this.ViewModel), "Create Session"); 
    } 

後PageManager.Close,唯一的東西引用的形式是視圖模型中的事件。我想這就是我應該解開它們的地方。

回答

2

析構函數,更俗稱爲C#程序員作爲終結者,在這種情況下不是必需的。假設ViewModel_LoadCompleted是一個成員函數,它包含一個指向「this」的指針,您將該指針賦予由「this」完全包含的ViewModel對象。垃圾回收器應該智能地忽略這個。

在這種情況下,正確的做法是不浪費時間去解除它們。

通常,當您將「this」(顯式地或隱式地)傳遞給某個持有該引用的對象比「this」的預期生存期更長時,您需要解除綁定事件處理函數。例如,如果您在父控件的事件上設置處理程序。現在父母通過處理程序以及其子控件集合對您進行引用。在這種情況下,當您從父項中移除時應該解除綁定。

如果有疑問,請在Dispose()的調用中實現IDisposable和unbind。

+0

Typo,「descructor」 – 2009-02-17 15:09:02

1

當垃圾收集器通過您的對象時,事件會自動解除綁定。

但是你可以用明確取消綁定他們 「 - =」 語法在任何時間:

this.ViewModel.LoadCompleted -= ViewMode_LoadCompleted; 

您可以實現一個析構函數:

~MyPage 
{ 
    this.ViewModel.LoadCompleted -= ViewMode_LoadCompleted; 
}