开发者

If I bind one control to the other, and one of the control dies, what happens to the binding?

fo开发者_开发技巧r example, let's take a programmatic binding:

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

myButton.SetBinding(Button.VisibilityProperty, binding);

What happens if myWindow dies and gets garbage collected... am I responsible for freeing up the binding as well, or does it know how to do that itself?


This is not true for Bindings, you'll have no memory leak even if you use Source for the Binding.

To verify this

  • Create a StackPanel, a TextBox (tb1) and two Buttons in Xaml
  • In code behind you create a new TextBox (tb2)
  • Set a Binding on tb1 with Source set to tb2
  • Create a WeakReference on tb2 (which shouldn't be GC'd if we have a leak)
  • Add tb2 to the StackPanel
  • Run the program and verify that the binding works
  • Click Remove
  • Click Is Alive?

It returns false, the source TextBox (tb2) has been garbage collected so we have no memory leak

Edit: You can also move the creation of the first TextBox from Xaml to code behind and use two WeakReferences (one for each TextBox) and verify that both textBoxes get GC'd properly and you'll see that this is true.

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>

Code Behind

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]);
    }
}


I think that it will not be garbage collected, as

The object is alive until the garbage collector finds out that the object is no longer reachable from a strong root reference via a path of strong references

from here Managing object lifetime

you still have a pointer binding.**Source** to it.


According to MSDN :

In C# garbage collection is handled by the comman language runtime (CLR) which is similar the Java's JVM. Garbage collecter periodically checks the memory heap for any unreferenced objects, and releases the resources held by these objects.

Therefore, in your example myWindow object cannot be garbage collected since there is a reference from binding object to myWindow.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜