DataGrid: memory leaks after items cleared
- 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
Assessment
This issue has not been assessed yet.