dotnet / dotnet/wpf

DataGrid: memory leaks after items cleared

Open
#6,983 2 comments 2 reactions 0 assignees View on GitHub
:construction: work in progress Investigate Performance
Dominant language
C#
Stars
7.7k
Forks
1.3k
Avg merge
1d 11h
Merged PRs (30d)
61

Description

There appear to be multiple memory leaks in DataGrid.

It feels like it was never tested for memory leaks after the items were cleared.

After a DataGrid is cleared (items collection view is empty), several properties and fields are still holding onto an item that was last selected. I don't see any logic that would clear this field after things are deselected or cleared.

These fields need to be cleared when selection is cleared (directly or via selected items being deleted):

https://github.com/dotnet/wpf/blob/b63c69eaf5b58e758765a37bb18064bbc94832ad/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/DataGrid.cs#L8652

https://github.com/dotnet/wpf/blob/b63c69eaf5b58e758765a37bb18064bbc94832ad/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/DataGrid.cs#L2806

https://github.com/dotnet/wpf/blob/b63c69eaf5b58e758765a37bb18064bbc94832ad/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/DataGrid.cs#L3423

and potentially

https://github.com/dotnet/wpf/blob/b63c69eaf5b58e758765a37bb18064bbc94832ad/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/DataGrid.cs#L2849

https://github.com/dotnet/wpf/blob/b63c69eaf5b58e758765a37bb18064bbc94832ad/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/DataGrid.cs#L2882

As a workaround, I wrote an extension method that you call after setting the ItemsSource on the DataGrid:

```csharp
private static readonly FieldInfo _selectionAnchorField = typeof(DataGrid).GetField("_selectionAnchor", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo _focusedInfoField = typeof(ItemsControl).GetField("_focusedInfo", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly PropertyInfo FocusedCellProperty = typeof(DataGrid).GetProperty("FocusedCell", BindingFlags.Instance | BindingFlags.NonPublic);

///
/// https://github.com/dotnet/wpf/issues/6983
///
public static void FixDataGridClearingLeak(this DataGrid dataGrid)
{
var items = dataGrid.ItemsSource;
if (items is IEnumerable)
{
var view = CollectionViewSource.GetDefaultView(items);
view.CollectionChanged += (s, e) =>
{
if (view.IsEmpty)
{
_selectionAnchorField.SetValue(dataGrid, null);
_focusedInfoField.SetValue(dataGrid, null);
FocusedCellProperty.SetValue(dataGrid, null);

dataGrid.CurrentItem = null;
dataGrid.CurrentCell = default;
dataGrid.CurrentColumn = null;
}
};
}
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.