2011-02-05 30 views
6

我在StackOverflow上看到了關於如何正確刪除WPF中的控件的問題。通常有一些評論你不會手動(或不能)處理它們,只要你沒有提及它們,它們最終將被GC清除。我很意外地注意到,我認爲我刪除的一個控件即使將其從父項中移除,也仍然在繼續工作。WPF - 刪除具有DispatcherTimer的控件似乎沒有消失

我已經在儘可能少的行中重新創建了示例。該控件具有DispatcherTimer。 這是我想要刪除的控件背後的WPF代碼。

public partial class MyControl : UserControl 
{ 
    private DispatcherTimer timer; 
    public MyControl() 
    { 
     InitializeComponent(); 
     timer = new DispatcherTimer(); 
     timer.Tick += TimerOnTick; 
     timer.Interval = TimeSpan.FromSeconds(1); 
     timer.Start(); 
    } 

    private void TimerOnTick(object sender, EventArgs args) 
    { 
     //this continues to get written out even after this control is removed. 
     System.Diagnostics.Debug.WriteLine("Tick From MyControl."); 
    } 

} 

這裏是背後對於添加和刪除我的控制窗口中的代碼。

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    private void AddClicked(object sender, RoutedEventArgs e) 
    { 
     anyControlHolder.Children.Add(new MyControl()); 
    } 

    private void RemoveClicked(object sender, RoutedEventArgs e) 
    { 
     anyControlHolder.Children.Clear(); 
    } 
} 

當我動態運行該代碼,然後添加和刪除自定義用戶控件(MyControl)我遇到的問題是,它的計時器保持滴答(在這個例子中,你可以看到它的寫出來的消息輸出窗口),並繼續在其tick事件中工作。 我應該使用什麼樣的模式來至少導致計時器在控件被移除時停止滴答滴答?

+0

添加卸載的事件似乎已工作。看來我應該也在看一個WeakEventPattern。有沒有人有這方面的建議? private void UserControl_Unloaded(object sender,System.Windows.RoutedEventArgs e) timer.Stop(); } – DTig 2011-02-05 04:00:38

回答

2

另一件事我會刪除您爲滴答事件添加的事件處理程序。任何你手動添加的東西都應該刪除。
至於實施WeakEventPattern你可能想看看這個article

4

您可以掛接到控件的空載事件並調用timer.Stop()內。我剛剛測試了這種情況,當調用anyControlHolder.Children.Clear()時會引發Unloaded事件,從而停止調試消息。

代碼:

public partial class MyControl : UserControl { 
    private DispatcherTimer timer; 

    public MyControl() { 
     InitializeComponent(); 

     this.Loaded += new RoutedEventHandler(MyControl_Loaded); 
     this.Unloaded += new RoutedEventHandler(MyControl_Unloaded); 
    } 

    void MyControl_Loaded(object sender, RoutedEventArgs e) { 
     timer = new DispatcherTimer(); 
     timer.Tick += TimerOnTick; 
     timer.Interval = TimeSpan.FromSeconds(1); 
     timer.Start(); 
    } 

    void MyControl_Unloaded(object sender, RoutedEventArgs e) { 
     timer.Stop(); 
    } 

    private void TimerOnTick(object sender, EventArgs args) { 
     Debug.WriteLine("Tick From MyControl."); 
    } 
} 

希望這有助於!