Если я связываю один элемент управления с другим, и один из элементов управления умирает, что происходит с привязкой? - PullRequest
2 голосов
/ 25 августа 2011
Например,

, давайте возьмем программную привязку:

Binding binding = new Binding("MyProperty");
binding.Converter = new BooleanToVisibilityConverter();
binding.Source = myWindow.myObject

myButton.SetBinding(Button.VisibilityProperty, binding);

Что произойдет, если myWindow умрет и соберет мусор ... Я также отвечаю за освобождение привязки или знает, каксделать это сам?

Ответы [ 3 ]

2 голосов
/ 25 августа 2011

Это не относится к привязкам, у вас не будет утечки памяти, даже если вы используете Source для Binding.

Чтобы проверить это

  • Создайте StackPanel, TextBox (tb1) и два Buttons в Xaml
  • В коде позади вы создаете новый TextBox (tb2)
  • Установите Binding на tb1 с Source, установленным на tb2
  • Создать WeakReference на tb2 (который не должен быть GC'd, если у нас есть утечка)
  • Добавить tb2 к StackPanel
  • Запустите программу и убедитесь, что привязка работает
  • Нажмите Удалить
  • Клик жив?

Возвращает значение false, источник TextBox (tb2) был удален, поэтому у нас нет утечки памяти

Редактировать: Вы также можете переместить создание первого TextBox из Xaml в код позади и использовать два WeakReferences (по одному на каждый TextBox) и убедиться, что оба текстовых поля получают GC ' правильно, и вы увидите, что это правда.

Xaml

<StackPanel Name="stackPanel">
    <TextBox Name="textBox"/>
    <Button Name="removeButton" Content="Remove" Click="removeButton_Click"/>
    <Button Name="isAliveButton" Content="Is Alive?" Click="isAliveButton_Click"/>
</StackPanel>

Код сзади

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        TextBox toBeGCdTextBox = new TextBox();
        stackPanel.Children.Add(toBeGCdTextBox);
        Binding textBinding = new Binding
        {
            Path = new PropertyPath("Text"),
            Source = toBeGCdTextBox
        };
        textBox.SetBinding(TextBox.TextProperty, textBinding);
        _weak = new WeakReference(toBeGCdTextBox);
    }
    private WeakReference _weak;
    private void isAliveButton_Click(object sender, RoutedEventArgs e)
    {
        GC.Collect();
        MessageBox.Show(_weak.IsAlive.ToString());
    }

    private void removeButton_Click(object sender, RoutedEventArgs e)
    {
        Debug.Assert(_weak.Target == stackPanel.Children[3]);
        stackPanel.Children.Remove(stackPanel.Children[3]);
    }
}
1 голос
/ 25 августа 2011

Я думаю, что не будет собирать мусор, так как

Объект жив, пока сборщик мусора не обнаружит, что объект больше не доступен из сильного корняссылка через путь сильных ссылок

отсюда Управление временем жизни объекта

у вас еще есть указатель binding.**Source** на него.

0 голосов
/ 25 августа 2011

Согласно MSDN:

В C # сборка мусора обрабатывается средой выполнения языка комманд (CLR), которая похожа на JVM Java.Сборщик мусора периодически проверяет кучу памяти для любых не связанных объектов и освобождает ресурсы, содержащиеся в этих объектах.

Поэтому в вашем примере объект myWindow не можетбыть сборщиком мусора, так как есть ссылка от объекта привязки к myWindow.

...