Monday, November 1, 2010

WPF Gird Causing Memory Leak

There is a fundamental problem in WPF that can cause a memory leak in applications using it.  The problem is that a ColumnCollection in a Grid can become pinned in memory. It is not in all cases but in a specific case in the application I work on.  I am not 100% about what in the structure caused it but there are 3 separate potential contributing culprits that I've identified.  Without extensive testing of the different scenarios I won't be able to identify exactly what the cause was.  The three potential contributing culprits are:

1.     User control inside a DataTemplate with a Grid.  It does not matter how deep in the control the grid was in the control all Grids were getting caught
2.     Binding column widths from a parent grid to an inner grid through a border control.  This was done to emulate a grid like behavior but allow for multiple control types within the grid
3.     Binding and unbinding the collection view source every time the source of the observable collection changed. 
In trying to fix this problem it seemed as if it was related to the DataTemplate but it is unclear exactly what caused the issue. 
The actual leak came from the pinning of the Grid.ColumnCollection.  The pinning of that caused all the associated control to be pinned as well.  The Grid.RowCollection did not seem to have the same issue.  This was still an issue even if there were no columns defined.  It also occurred if a Grid was used inside a control from the same assembly.  If the Grid was anywhere inside a user defined control in the same assembly, at any level, the issue would occur, even if it was in another user control.  Crossing the assembly boundary appears to make this not occur. 
To fix the issue I replaced the Grids in the affected controls.  The grids were replaced with a combination of StackPanels and DockPanels which can be used to replicate the grid.  In this case they were actually more appropriate than using a Grid anyway. 
The lesson from this appears to be that the use of a Grid over other LayoutPanel types should be carefully considered.  If memory leaks start to appear with the Grid it needs to be changed to another Layout type.