Can binding ItemsControl to a non-ObservableCollection cause memory leaks? - wpf

While researching potential causes of memory leaks in WPF applications I came across this article:
https://oz-code.com/blog/net-c-tips/top-3-memory-leak-inducing-pitfalls-of-wpf-programming
This article makes the following unsubstantiated claim (which it admits to) that binding to collections other than ObservableCollection cause leaks:
Avoid binding to collections that are not ObservableCollection
I’m a bit sketchy on the details on this one. I haven’t yet been able
to find the root cause of this issue, or find any corroborating blog
post or MSDN articles, but still: in several instances, I’ve found
memory leaks occurred when an ItemsControl was bound to an ICollection
that isn’t an ObservableCollection, and changing it to an
ObservableCollection solved the problem.
Is this an accurate statement? Or is there some other more likely explanation?
I wonder if what the OP described might have been caused by binding to objects that don't implement INotifyPropertyChanged? (https://stackoverflow.com/a/18543350/3195477).

Not exactly quite what the OP asked, but close enough to help, I hope: https://blog.jetbrains.com/dotnet/2014/09/04/fighting-common-wpf-memory-leaks-with-dotmemory/ states:
Collection binding leak
A similar issue to the WPF binding leak is the
Collection binding leak. If there is binding to a collection that does
not implement the INotifyCollectionChanged interface, WPF creates a
strong reference to this collection. As a result, it stays in memory
for the entire application lifetime.

Related

Is it wrong to access TreeViewItems in WPF’s TreeView?

I’ve been having issues with the TreeView in WPF. This control makes it very hard to access the TreeViewItems it’s showing.
On several occasions I have worked around the need to access a TreeViewItem, for example I’ve accepted the fact that I’m not supposed to access a node’s parent via TreeView (and am supposed to instead keep track of the parent myself). I’ve been doing this for two reasons: first, it’s obviously extremely hard to get at the TreeViewItems, and secondly, I’ve been told that it’s hard because I’m not supposed to need them if I do things right.
However, this time I really see no way around this.
Basically, all I want is, given one of my viewmodel instances, scroll the tree view to it. This is trivial if I could just get the corresponding TreeViewItem.
Am I doing things wrong again by trying to get at the TreeViewItem, or would that be the right approach?
Take a look at Simplifying the WPF TreeView by Using the ViewModel Pattern article by Josh Smith. I hope it helps.
Admittedly this is not straightforward but you can probably still do this while keeping a separation which does not require you to access the TreeViewItems knowingly. The essence in WPF is binding as already noted by Kent Boogaart in your other question, here however you need to somehow deal with events. Your view-model needs to fire a BringIntoView event of its own while the view needs to react.
The easiest method might be to add a EventSetter on Loaded to make the TreeViewItems subscribe to said event on their DataContext which should be your view-model (if it isn't you can wait for DataContextChanged).
No, I dont see in what way accessing the items of a treeview is wrong.
I think the difficulties you are encountering are because you aren't seeing the treeview as it should be.
A leaf has a parent, but no children.
A node can have a parent, and can have children.
A node without a parent is a root.
Based on these principles (SourceMaking Composite pattern) you should be able to do whatever you want using recursivity. (in both XAML and code)
I’ve come to the conclusion that it can’t be altogether wrong. The first piece of evidence comes from Bea Stollnitz’s post about ListView: if one of the WPF developers explains how this might be done, it can’t be that wrong.
The other piece of evidence comes from this highly-voted question/answer: MVVM madness. MVVM undoubtedly has its benefits, but sometimes the cost of following MVVM is so high that it’s just silly following through with it, especially in a small one-man application. Do you really want to expose IsSelected and IsExpanded the way you’re supposed to?
As a result, I felt justified to try and figure out how to expose the TreeViewItem corresponding to an item with less effort from the developer, under the assumption that they will never need the more advanced features that resulted in TreeViewItems being this hard to access (like displaying the same ViewModels in multiple different controls... how often have you needed that!...)
I posted the result of this effort as an answer on another question.

WPFToolkit Charts leak memory, any fixes or alternatives?

I've found that the chart controls in the WPFToolkit library leak memory. I am using them in an MVVM setup, where I bind the ItemSource of the chart control (PieSeries or BarSeries) to an ObservableCollection on my ViewModel. I sometimes Clear() the ObservableCollection and then Add() new KeyValuePairs to it (when the user triggers a SelectionChanged event on a ComboBox to see a different set of data). That's how I change the data in the chart. However, the memory is not released. I've found that if I comment out the control in the XAML, the memory problem goes away, even if I still Add to the collection.
Are there any good fixes for this memory leak? Or alternative toolkits that are free?
Thanks!
This seems to be a known issue, here is a quick fix:
<dvc:Chart.Palette>
<dv:ResourceDictionaryCollection>
<!-- Note: This a memory leak fix, do not remove-->
</dv:ResourceDictionaryCollection>
</dvc:Chart.Palette>
Found here: http://wpf.codeplex.com/discussions/216609

Memory Leak with CollectionViewSource.GetDefaultView() in WPF?

I'm wondering what the best practices are for working with CollectionViews in WPF in particular the use of the CollectionViewSource.GetDefaultView() method. Has anyone run into any problems with using GetDefaultView? We're concerned that it may be causing some memory leaks.
Is it generally a better practice to create ListCollectionViews manually rather than rely on GetDefaultView()?
How does WPF manage these views? Do they get GC'd when the collection does? I've seen some articles saying that you need to detach CollectionViews from their source collection otherwise you'll have a memory leak.
Thanks for you help!
Bea states that using CollectionViewSource.GetDefaultView() is her favorite way for accessing the view of a given collection. In addition I have personally never ran into any issues making use of the CollectionViewSource.GetDefaultView() however it is certainly possible in a given scenario.
You have to understand that every collection has a default view and that when you bind a given property to a given collection WPF automatically wraps the collection with a view and binds to the view; not the collection.
Since this is part of the WPF framework you then have to assume that with every collection having a view associated with it that it would then be disposed of when the collection is disposed of. If there is a reference to the collection via a bindable property there is then an associated view referencing the collection whether you make a call to CollectionViewSource.GetDefaultView() or not so you would still be in the same predicament.
Empirical evidence exists that until the collection is out of scope the associated views will not be GC'ed; however keep in mind that this was dealing with a collection with implements INotifyCollectionChanged.
Based on your circumstance a 1:1 relationship between the collection and associated view may exist and therefore the coupling may provide no hindrance whatsoever. In this scenario the view being GC'ed once the collection has gone out of scope is not an issue.
It boils down to treading with caution and making certain that you know what is happening under the covers for the more complex situations so that you can take the appropriate measures.

What's the best way to avoid memory leaks in WPF PRISM/MVVM application

I have a WPF application based on PRISM that utilizes the MVVM pattern.
I have noticed that occasionally my view models, views and everything connected to them will hang around long after their intended lifespan.
One leak involved subscribing to CollectionChanged on a collection belonging to an injected service, another involved not calling the Stop method on a DispatcherTimer, and yet another required a collection be cleared of it's items.
I feel using a CompositePresentationEvent is probably preferable to subscribing to CollectionChanged, but in the other scenarios I am leaning towards implementing IDisposable and have the views call the Dispose method on the view models.
But then something needs to tell the view when to call Dispose on the view model, which gets even less attractive when the complexity of the views increase, and they start including child views.
What do you think is the best approach to handling view models, to ensure they don't leak memory?
Thanks in advance
Ian
I can tell you that I've experienced 100% of the pain you have experienced. We are memory leak brothers, I think.
Unfortunately the only thing I've figured out to do here is something very similar to what you are thinking.
What we've done is create an attached property that a view can apply to itself to bind a handler to the ViewModel:
<UserControl ...
common:LifecycleManagement.CloseHandler="{Binding CloseAction}">
...
</UserControl>
Then our ViewModel just has a method on it of type Action:
public MyVM : ViewModel
{
public Action CloseAction
{
get { return CloseActionInternal; }
}
private void CloseActionInternal()
{
//TODO: stop timers, cleanup, etc;
}
}
When my close method fires (we have a few ways to do this... it's a TabControl UI with "X" on the tab headers, that kind of thing), I simply check to see if this view has registered itself with the AttachedProperty. If so, I call the method referenced there.
It's a pretty roundabout way of simply checking to see if the DataContext of a View is an IDisposable, but it felt better at the time. The problem with checking the DataContext is you might have sub view models that also need this control. You'd either have to make sure your viewmodels chain forward this dispose call or check all of the views in the graph and see if their datacontexts are IDisposable (ugh).
I sort of feel like there is something missing here. There are a few other frameworks that attempt to mitigate this scenario in other ways. You might take a look at Caliburn. It has a system for handling this where a ViewModel is aware of all sub view models and this enables it to automatically chain things forward. In particular, there is an interface called ISupportCustomShutdown (I think that's what it's called) that helps mitigate this problem.
The best thing I've done, however, is make sure and use good memory leak tools like Redgate Memory Profiler that help you visualize the object graph and find the root object. If you were able to identify that DispatchTimer issue, I imagine you are already doing this.
Edit: I forgot one important thing. There is a potential memory leak caused by one of the event handlers in DelegateCommand. Here's a thread about it on Codeplex that explains it. http://compositewpf.codeplex.com/WorkItem/View.aspx?WorkItemId=4065
The latest version of the Prism (v2.1) has this fixed. (http://www.microsoft.com/downloads/details.aspx?FamilyID=387c7a59-b217-4318-ad1b-cbc2ea453f40&displaylang=en).
My findings so far...
In addition to PRISM, Unity, WPF and MVVM we are also using Entity Framework and the Xceed data grid. Memory profiling was done using dotTrace.
I ended up implementing IDisposable on a base class for my view models with the Dispose(bool) method being declared virtual allowing sub classes the chance to clean up as well.
As each view model in our application gets a child container from Unity we dispose it as well, in our case this ensure that EF's ObjectContext went out of scope. This was our major source of memory leaks.
The view model is disposed within an explicit CloseView(UserControl) method on a base controller class. It looks for an IDisposable on the DataContext of the view and calls Dispose on it.
The Xceed data grid seems to be causing a fair share of the leaks, especially in long running views. Any view that refreshes the data grid's ItemSource by assiging a new collection should call Clear() on the existing collection before assigning the new one.
Be careful with Entity Framework and avoid any long running object contexts. It's very unforgiving when it comes to large collections, even though you have removed the collection if tracking is turned on, it will hold a reference to every item in the collection even though your no longer hanging on to them.
If you don't need to update the entity retrieve it with MergeOption.NoTracking, especially in long lived views that bind to collections.
Avoid views with a long life, don't hold onto them within a region when they are not visibile, this will cause you grief especially if they refresh their data at regular intervals when they are visible.
When using CellContentTemplates on the Xceed Column don't use dynamic resources as the resource will hold a reference to the cell, which in turn keep the entire view alive.
When using CellEditor on the Xceed Column and the resource is stored in an external resource dictionary add x:Shared="False" to the resource containing the CellEditor, once again the resource will hold a reference to the cell, using x:Shared="False" ensures you get a fresh copy each time, with the old one being removed correctly.
Be careful when binding the DelegateCommand to items within the Exceed data grid, if you have a case such as a delete button on the row which binds to a command, be sure to clear the collection containing the ItemsSource before closing the view. If you're refreshing the collection you also need to reinitialize the command as well as the command will hold a reference to each row.

Silverlight databinding internal workings

Does anyone know how the databinding system works in silverlight technically, I have seen alot of the tuts on databinding and that items must be bound to a Dependancy Object ( and dependants ) using dependancy properties but where are the properties actually managed? what classes should I look at in reflector to understand the internals? I want a deeper look can anyone explain it better?
The data binding is handled by the unmanaged stack so you can't exactly do it but you can look at the stack in wpf a little easier. Essentially, the DependencyObject stuff is so that execution of changes is a lot faster than reflection can do. Remember this stack is also responsible for animation changes. (30-60x second).

Resources