2010-11-26 28 views
6

我一直在調查爲什麼我的一些控件沒有被垃圾收集,並且發現很容易阻止從ContentControl繼承的簡單控件被破壞。這裏有一個例子:爲什麼Silverlight ContentControls不被垃圾收集?

這裏是我的自定義ContentControl中:

public class MyCustomControl : ContentControl 
{ 

    public MyCustomControl() 
    { 
     Debug.WriteLine("Constructed"); 
    } 

    ~MyCustomControl() 
    { 
     Debug.WriteLine("Destroyed"); 
    } 
} 

現在,如果我把它放在一個頁面上,像這樣:

<navigation:Page x:Class="SimpleTestBed.Views.CustomControl" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     mc:Ignorable="d" 
     xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" 
      xmlns:local="clr-namespace:SimpleTestBed" 
     d:DesignWidth="640" d:DesignHeight="480" 
     Title="CustomControl Page"> 
<Grid x:Name="LayoutRoot"> 

    <StackPanel> 
     <local:MyCustomControl> 
      <TextBox Text="{Binding SomeProperty,Mode=TwoWay}"></TextBox> 
     </local:MyCustomControl> 
    </StackPanel> 

</Grid> 

用下面的代碼背後:

public partial class CustomControl : Page 
{ 
    public CustomControl() 
    { 
     InitializeComponent(); 

     this.DataContext = new CustomControlViewModel(); 

     this.Unloaded += new RoutedEventHandler(OnUnloaded); 
    } 

    void OnUnloaded(object sender, RoutedEventArgs e) 
    { 
     this.DataContext = null; 
    } 

    // Executes when the user navigates to this page. 
    protected override void OnNavigatedTo(NavigationEventArgs e) 
    { 
    } 



} 

然後查看模型是:

public class CustomControlViewModel : INotifyPropertyChanged 
{ 

    #region INotifyPropertyChanged 
    public event PropertyChangedEventHandler PropertyChanged; 
    protected void OnPropertyChanged(string propertyName) 
    { 
     RaisePropertyChanged(propertyName); 
    } 
    private void RaisePropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
    #endregion 


    private string _someProperty = "Initial Value"; 
    public string SomeProperty 
    { 
     get { return _someProperty; } 
     set 
     { 
      if (_someProperty != value) 
      { 
       string oldValue = _someProperty; 
       _someProperty = value; 
       OnPropertyChanged("SomeProperty"); 
       OnSomePropertyChanged(oldValue, value); 
      } 
     } 
    } 



    protected virtual void OnSomePropertyChanged(string oldValue, string newValue) 
    { 

    } 


} 

現在,當我離開此頁面並嘗試使用GC.Collect()進行垃圾收集時,只要我沒有對文本框中的文本進行更改,ContentControl和Page按預期銷燬GC。但是,如果我編輯了一些文本並從頁面導航,然後嘗試GC.Collect(),則ContentControl不會被垃圾收集。

任何人都可以解釋這種行爲嗎?

其實,你可以強制GC的「閃爍」的控制模板收集控制,當你卸載:

void MyCustomControl_Unloaded(object sender, RoutedEventArgs e) 
    { 
     Debug.WriteLine("MyCustomControl Unloaded"); 
     ControlTemplate oldTemplate = this.Template; 
     this.Template = null; 
     this.Template = oldTemplate; 
    } 

我想這會破壞目前的可視化樹失去樹的第一個組件的引用到它的父母(自定義控件)。當控件重新加載時,它肯定會強制控件調用OnApplyTemplate。

這是開發Silverlight控件而不泄漏的正確模式嗎?如果是這樣,它會讓我感到有點奇怪,即控件卸載時模板不會自動處理。

對這種行爲的一個很好的描述將非常值得讚賞,因爲它正好適用於Silverlight控件生命週期的核心。

回答

-1

我的經驗表明,在Silverlight內存泄漏是由頂級的理由之二致毒:

  • 活動=>請確保您刪除不需要一旦當它附着事件或在類的析構。
  • 模板=>解決方案在資源部分定義模板
+0

爲什麼您的答案有關?這似乎不適用於OP – 2012-06-10 19:32:26