2009-02-17 27 views
5

Tóm tắt một dòng: Phương pháp hay nhất để gỡ bộ xử lý sự kiện được tạo trong trình tạo của UserControl trong Silverlight2 là gì?Khi nào cần hủy các sự kiện trong Silverlight

Bối cảnh: Tôi hiện đang xây dựng một ứng dụng kinh doanh trực tuyến trong Silverlight2. Như Silverlight là một plugin trình duyệt, không có khái niệm về một cửa sổ - tất cả mọi thứ được thực hiện trong UserControls. Cách tôi xử lý các "biểu mẫu" khác nhau trong ứng dụng là có một usercontrol cấp cao nhất có chứa một Viewbox. Để hiển thị các biểu mẫu khác nhau, tôi đặt thuộc tính Con của Hộp nhìn đến các UserControl khác nhau. Ứng dụng của tôi có lớp PageManager đơn được gọi để mở và đóng biểu mẫu. Các biểu mẫu (UserControls) được lưu trữ trong một ngăn xếp. Mở một biểu mẫu đặt nó lên trên cùng của ngăn xếp, đóng nó sẽ loại bỏ nó khỏi ngăn xếp và hiển thị nó bên dưới nó.

Tôi đang cố gắng theo mẫu Kiểu xem-ViewModel. Trong mỗi hình thức (bắt nguồn từ UserControl), tôi có một ViewModel quản lý tất cả các dữ liệu cho View. ViewModel hiển thị các sự kiện để giao diện người dùng có thể được thông báo khi các hoạt động như tải và lưu đã hoàn tất.

Ở dạng của tôi, tôi đăng ký vào các sự kiện trong các nhà xây dựng, sau khi tôi đã có ViewModel

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); 
    } 

Câu hỏi của tôi là: Bây giờ tôi đã đăng ký sự kiện này, khi nào tôi tháo xử lý? Tôi tạo ra một destructor và làm điều đó ở đó, hoặc không tạo ra một tình huống gà và trứng, nơi thu gom rác sẽ không phá hủy các đối tượng cho đến khi tất cả các tài liệu tham khảo (tức là: xử lý sự kiện) đã biến mất? Tôi có tạo một giao diện mà các biểu mẫu phải triển khai thực hiện một hàm UnhookEvents được gọi khi biểu mẫu được đóng bởi PageManager không?

Chỉnh sửa: Cảm ơn bạn đã trả lời. Điều gì về tình hình ViewModel kéo dài hơn biểu mẫu (UserControl)? Một phần của ứng dụng của tôi cho phép người dùng tạo ra cấu trúc khá phức tạp, nhưng trong 95% trường hợp nó đơn giản hơn nhiều. Những gì tôi đã làm là tạo ra 2 hình thức sử dụng cùng ViewModel. Người dùng có thể bắt đầu điền vào biểu mẫu đơn giản, sau đó chuyển sang chế độ nâng cao, tạo ra một biểu mẫu mới, chuyển ViewModel đến nó.

Trong hình thức cài đặt đơn giản:

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

Trong hình thức thiết lập nâng cao:

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

Sau PageManager.Close, điều duy nhất tham khảo dưới hình thức là những sự kiện trong ViewModel. Tôi đoán đó là nơi mà tôi nên cởi chúng.

Trả lời

2

Destructor, thường được biết đến với C# lập trình viên như Finalizers, là không cần thiết trong trường hợp này. Giả sử rằng ViewModel_LoadCompleted là một hàm thành viên, nó chứa một con trỏ tới "this" mà bạn đang đưa cho đối tượng ViewModel được chứa đầy đủ bởi "this". Các nhà sưu tập rác nên thông minh bỏ qua điều này.

Trong trường hợp này, điều đúng đắn cần làm là không lãng phí thời gian để liên kết chúng.

Nói chung, bạn cần hủy liên kết trình xử lý sự kiện khi bạn chuyển "điều này" (một cách rõ ràng hoặc ngầm) cho một số đối tượng sẽ giữ tham chiếu dài hơn thời gian dự định "này". Ví dụ: nếu bạn đặt trình xử lý trên sự kiện của kiểm soát của phụ huynh. Bây giờ phụ huynh có một tham chiếu đến bạn thông qua trình xử lý cũng như trong bộ sưu tập Kiểm soát trẻ em của nó. Trong trường hợp này, bạn nên hủy liên kết khi bạn bị xóa khỏi phụ huynh.

Khi nghi ngờ, hãy triển khai IDisposable và unbind trong lệnh gọi Dispose().

+0

Typo, "descructor" –

+0

Nếu ViewModel của tôi kéo dài hơn UserControl thì sao? (Tôi sẽ chỉnh sửa câu hỏi để hiển thị như thế nào) – geofftnz

+0

Nếu mô hình của bạn kéo dài hơn kiểm soát người dùng, bạn cũng không cần phải lo lắng về việc hủy liên kết. Mô hình không nên có tham chiếu đến điều khiển. Khi điều khiển vượt quá phạm vi, nó sẽ là rác được thu thập và sẽ không trỏ đến mô hình nữa. –

1

Sự kiện sẽ tự động được hủy khi trình thu thập rác đi qua đối tượng của bạn.

Nhưng bạn có thể unbind rõ ràng chúng với "- =" cú pháp bất cứ lúc nào:

this.ViewModel.LoadCompleted -= ViewMode_LoadCompleted; 

Bạn có thể thực hiện một destructor:

~MyPage 
{ 
    this.ViewModel.LoadCompleted -= ViewMode_LoadCompleted; 
} 
Các vấn đề liên quan