如果我将一个控件绑定到另一个控件,并且其中一个控件死亡,那么绑定会发生什么?

时间:2011-08-24 20:36:21

标签: c# wpf data-binding memory-leaks garbage-collection

例如,让我们采用程序化绑定:

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

myButton.SetBinding(Button.VisibilityProperty, binding);

如果myWindow死了并且收集了垃圾,会发生什么......我是否也负责释放绑定,或者它知道如何自己做这件事吗?

3 个答案:

答案 0 :(得分:2)

对于Bindings不是这样,即使您对Source使用Binding,也不会有内存泄漏。

验证这个

  • 在Xaml中创建StackPanelTextBox(tb1)和两个Buttons
  • 在后面的代码中,您创建一个新的TextBox(tb2)
  • 在tb1上设置BindingSource设置为tb2
  • 在tb2上创建一个WeakReference(如果我们有泄漏则不应该是GC)
  • 将tb2添加到StackPanel
  • 运行程序并验证绑定是否正常工作
  • 点击删除
  • 点击Is Alive?

它返回false,源TextBox(tb2)已被垃圾收集,因此我们没有内存泄漏

修改:您还可以将第一个TextBox的创建从Xaml移至代码隐藏,并使用两个WeakReferences(每个TextBox一个)验证两个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 :(得分:1)

我认为它将被垃圾收集,如

  

对象是活着的,直到垃圾收集器发现了   无法再通过路径从强根引用访问对象   强引用

从这里Managing object lifetime

你仍然有一个指针binding.**Source**

答案 2 :(得分:0)

根据MSDN:

  

在C#中,垃圾收集由comman语言运行时处理   (CLR)与Java的JVM类似。垃圾收集器定期   检查内存堆中是否有任何 未引用的 对象,以及   释放这些对象持有的资源。

因此,在您的示例中,myWindow对象无法进行垃圾回收,因为存在从绑定对象到myWindow的引用。