Can bindings create memory leaks in WPF?
If you are not binding to a DependencyProperty
or a object that implements INotifyPropertyChanged
then the binding can leak memory, and you will have to unbind when you are done.
This is because if the object is not a DependencyProperty
or does not implement INotifyPropertyChanged
then it uses the ValueChanged
event via the PropertyDescriptors
AddValueChanged
method. This causes the CLR to create a strong reference from the PropertyDescriptor
to the object
and in most cases the CLR will keep a reference to the PropertyDescriptor
in a global table.
Because the binding must continue to listen for changes. This behavior keeps the reference alive between the PropertyDescriptor
and the object
as the target remains in use. This can cause a memory leak in the object
and any object
to which the object
refers, This includes the data-binding target.
So in short if you are binding to a DependencyProperty
or INotifyPropertyChanged
object then you should be ok, otherwise like any subscribed event you should unsubscribe your bindings
Edit: There is a possibility this was fixed in .NET4.5 using Weak Events/References, But after a few quick tests it seemed the same to me, I will have to dive in more deeply to confirm, so I'll personally say in might be fixed in 4.5 :)
Not pretend to answer, just for reference. In a classic article on Finding Memory Leaks in WPF-based applications
author Jossef Goldberg, described in detail cases, where there may be a memory leak in WPF application. Really, most relate to the .NET 3.5/4.0, but some cases may be relevant to this day. Also, have a small extension.
Quote about leak in Binding
:
Cause:
This leak documented in this kb article. It is triggered because:
The TextBlock
control has a binding to an object (myGrid) that has a reference back to the TextBlock
(it is one of myGrid children’s).
Note:
that this type of a DataBinding leak is unique to a specific scenario (and not to all DataBinding scenarios) as documented in the kb article. The property in the Path
is a not a DependencyProperty
and not on a class which implements INotifyPropertyChanged
and in addition a chain of strong references must exist.
Code:
myDataBinding = new Binding("Children.Count");
myDataBinding.Source = myGrid;
myDataBinding.Mode = BindingMode.OneWay;
MyTextBlock.SetBinding(TextBlock.TextProperty, myDataBinding);
Same leaky code can be also written in XAML:
<TextBlock Name="MyTextBlock"
Text="{Binding ElementName=myGrid, Path=Children.Count}" />
Fix/Workaround:
There are few of approaches, the easiest one is simply to clear the binding when the windows is about to close.
e.g.:
BindingOperations.ClearBinding(MyTextBlock, TextBlock.TextProperty);
Other approach is to set the mode of the data binding to OneTime. See the kb article for other ideas.
Useful link:
Avoiding a WPF memory leak with DataBinding
From http://msdn.microsoft.com/en-us/library/aa970850.aspx, WPF uses Weak Event Patterns, which do not hold strong references to objects and allow them to be GC'ed if they are the only references to an object.
"Many aspects of WPF data binding already have the weak event pattern applied in how the events are implemented."
But weak events are only used on DependencyProperties
and INotifyPropertyChanged
object, so if you are binding to a POCO with a binding mode other than OneTime
you could end up leaking memory.