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 :)
Why does implementing INotifyPropertyChanged avoid memory leaks in WPF?
If a property does not implement the INotifyPropertyChanged interface, then the WPF framework will stupidly add one for you by subscribing to the PropertyDescriptor.ValueChanged event. Since WPF and the CLR do not know when to dispose of / unsubscribe from the event, it holds on to the property forever. And since the property is being referenced, it can not be garbage collected. The whole instance of the class that contains that property stays in memory forever, thus causing a memory leak.
ICommand binding causing UI memory leak in WPF application
The CanExecuteChanged
event handler is likely implicated in the leak.
WPF expects ICommand implementations to use weak references to the event handlers. You're using a normal .NET event which uses strong references, which can cause this leak.
The way you are creating the ParameterlessCommand
instance seems to imply that CanExecute
will always be true, and you don't need the event at all.
Are you actually firing the event anywhere, or is OnCanExecuteChanged
unused code?
If not, replace the event definition with:
public event EventHandler CanExecuteChanged { add {} remove {} }
This way the event does not store any handlers, and the view model avoids having a strong reference to the UI elements.
If you need to raise the event, the easiest solution is to use CommandManager.RequerySuggested
, which matches the weak event semantics expected for ICommand:
public event EventHandler CanExecuteChanged {
add {
CommandManager.RequerySuggested += value;
}
remove {
CommandManager.RequerySuggested -= value;
}
}
Another thing you should do is implement INotifyPropertyChanged
in your view model (if you haven't done so already), and use that instead of having individual NameChanged
etc. events for each property.
This is because the logic in WPF dealing with the individual properties causes memory leaks when there is a reference from the view model back to the UI elements: http://support.microsoft.com/kb/938416
AFAIK you need to implement INotifyPropertyChanged
even if you don't actually have any change events.
My guess is that fixing either of these two problems will make the leak disappear: the incorrectly implemented CanExecuteChanged
causes a strong reference from view model to view, which is exactly the circumstance under which the lack of INotifyPropertyChanged
causes a leak.
But it's a good idea to fix both issues; not just one of them.
WPF - Is changing binding expression from one to another may cause to memory leak?
Is it possible to cause memory leak if I change the binding by trigger.
In general, there's no more potential for a leak than there would be with just a single binding. That's not to say that a leak is impossible, but if you follow the best practices and make sure anything you bind to implements INotifyPropertyChanged
, then you won't accidentally cause your binding source to be retained. Binding expressions use weak references to refer to the bound object, so that won't cause a leak.
Specifically, the example you posted looks fine, and should not cause a leak.
I read somewhere (and I can't find it right now) that there are scenarios where if you give to an element the property x:Name then you may cause to memory leak.
The case would be when you remove an element with an x:Name
directive from your UI tree. The reason is that x:Name
doesn't just set the Name
property; it also registers the element in the name scope, and that registration involves a strong reference. If you remove a named element from the UI without also removing it from the name scope, then it will be kept alive until the name scope becomes unreachable.
When removing a named element, call UnregisterName
in the parent view, passing in the name of the element you are removing. That will remove it from the name scope.
Related Topics
ASP.NET Urlencode Ampersand for Use in Query String
Datetime.Tryparse Century Control C#
Can You Configure Log4Net in Code Instead of Using a Config File
Weak Event Handler Model for Use with Lambdas
Convert File Path to a File Uri
Adding Stored Procedures Complex Types in Entity Framework
Am I Misunderstanding Linq to SQL .Asenumerable()
Trying to Insert Datetime.Now into Date/Time Field Gives "Data Type Mismatch" Error
Get Value of C# Dynamic Property via String
Displayname Attribute VS Display Attribute
Populate Treeview with File System Directory Structure
How to Transfer Authentication from Webbrowser to Webrequest
Mvc/Jquery Validation Does Not Accept Comma as Decimal Separator