Почему Silverlight ContentControls не выполняет сборку мусора?

Я исследовал, почему некоторые из моих элементов управления не собираются сборщиком мусора, и заметил, что легко предотвратить уничтожение простых элементов управления, наследуемых от ContentControl. Вот пример:

Вот мой пользовательский 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 и страница будут уничтожены, как и ожидалось GC. Но если я отредактировал какой-то текст и ушел со страницы, а затем попытался использовать GC.Collect (), ContentControl не не собирать мусор.

Кто-нибудь может объяснить такое поведение?

Фактически, вы можете заставить сборщик мусора собирать элемент управления, «мигая» шаблоном элемента управления при выгрузке:

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

Я полагаю, это уничтожает текущее визуальное дерево, теряя ссылки первого компонента дерева на его родительский элемент ( пользовательский контроль). Это, безусловно, заставляет элемент управления вызывать OnApplyTemplate при перезагрузке элемента управления.

Это правильный шаблон для разработки элементов управления Silverlight без утечек? Если это так, мне кажется немного странным, что шаблон не удаляется автоматически при выгрузке элемента управления.

Хороший отчет об этом поведении был бы очень признателен, поскольку он лежит в основе жизненного цикла элементов управления Silverlight.

6
задан Stephen Ellis 27 November 2010 в 09:48
поделиться