Почему ваш ответ актуален? Это не относится к ФП

чал, почему некоторые из моих элементов управления не собирали мусор, и заметил, что легко предотвратить уничтожение простых элементов управления, которые наследуются от 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 (), до тех пор, пока я не внесу никаких изменений в текст в Textbox, 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)

Ваш ответ на вопрос