2010-11-26 69 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