ContextMenu causes a memory leak

I spent the last few days trying to track a memory leak in my WPF application, and I think I nailed it to ContextMenu.

If the user opens the context menu (in my application it is necessary to delete the view / viewModel, which always happens before deleting), then even after deleting all the links to the ViewModel and the view is no longer displayed in VisualTree, the objects save some links in the memory profiler, and the data are not freed, which causes a memory leak.

I made a small example containing ViewModel ExampleViewModel:

public class ExampleViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string name;
    public string Name
    {
        get { return name; }
        set {
            name = value;
            OnPropertyChanged("Name");
        }
    }

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
}

With a nice simple view and contextMenu:

<UserControl x:Class="ContextMenuMemoryLeak.ExampleView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:ContextMenuMemoryLeak"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <TextBox Text="{Binding Name}">
        <TextBox.ContextMenu>
            <ContextMenu>
                <TextBlock Text="Text"/>
            </ContextMenu>
        </TextBox.ContextMenu>
    </TextBox>
</UserControl>

The window adds and removes them to the ObservableCollection:

    public partial class MainWindow : Window, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        ViewModels = new ObservableCollection<ExampleViewModel>();
    }

    private ObservableCollection<ExampleViewModel> viewModels;
    public ObservableCollection<ExampleViewModel> ViewModels
    {
        get { return viewModels; }
        set {
            viewModels = value;
            OnPropertyChanged("ViewModels");
        }
    }

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        for (int i = 0; i < 10; i++)
        {
            ViewModels.Add(new ExampleViewModel { Name = $"Item {i}" });
        }
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        ViewModels.Clear();
    }
}

And displays them:

<Window x:Class="ContextMenuMemoryLeak.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ContextMenuMemoryLeak"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <Button Click="Button_Click">Add More</Button>
        <Button Click="Button_Click_1">Remove All</Button>
        <ListBox ItemsSource="{Binding ViewModels}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <local:ExampleView DataContext="{Binding}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </StackPanel>
</Window>

ExampleViewModels, . 10 , :

enter image description here

10. 5 ( ), :

enter image description here

5 View ViewModels ... !

, ( , - , - ), , google ... , , google.

, ? ?

: " " ViewModel, :

enter image description here

:

enter image description here

, - ( , , DOES !):

enter image description here

+4

Source: https://habr.com/ru/post/1667353/


All Articles