简体   繁体   中英

WPF: ObservableCollection Memory leak

[I'm sorry for my bad English]

In my MainWindow I have some ContentControl and I set his Content to some view called SimpleView . If that SimpleView has ListBox bounded to Collection, The view is alive even if I remove the SimpleView .

All my viewmodels are Implementing INotifyPropertyChanged. This is my code:

MainWindow.xaml

<Window x:Class="WpfMemory.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
            <Button Content="Set view" Click="SetView" />
            <Button Content="Clear view" Click="ClearView" />
        </StackPanel>

        <ContentControl x:Name="ViewContainer" Grid.Row="1" Margin="4" />
    </Grid>
</Window>

In code behind

private void SetView(object sender, RoutedEventArgs e)
{
    var simpleViewModel = new ViewModels.SimpleViewModel();
    var simpleview = new Views.SimpleView() { DataContext = simpleViewModel };
    ViewContainer.Content = simpleview;
}

private void ClearView(object sender, RoutedEventArgs e)
{
    ViewContainer.Content = null;
    System.GC.Collect();
}

SampleView.xaml

<UserControl x:Class="WpfMemory.Views.SimpleView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition MinWidth="60"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition />
        </Grid.RowDefinitions>

        <TextBlock Text="SomeText" />
        <TextBox Text="{Binding SomeText}" Grid.Column="1"/>

        <TextBlock Text="Large data" Grid.Row="1"/>
        <ListBox ItemsSource="{Binding LargeData,Mode=OneTime}" 
                 Grid.Row="2" Grid.Column="1" 
                 DisplayMemberPath="Name" />

    </Grid>
</UserControl>

View models

public sealed class SimpleViewModel : ViewModelBase
{
    public SimpleViewModel()
    {
        var items = Enumerable.Range(1, 10000)
            .Select(x => new SimpleItem()
            {
                Id = x,
                Name = "Item " + x
            })
            .ToArray();

        LargeData = new ObservableCollection<SimpleItem>(items);
    }

    public string SomeText{ get; set; } = "yehudah";

    ObservableCollection<SimpleItem> largeData;
    public ObservableCollection<SimpleItem> LargeData
    {
        get { return largeData; }
        set { SetProperty(ref largeData, value); }
    }
}

public sealed class SimpleItem : ViewModelBase
{
    public int Id { get; set; }
    public string Name { get; set; }
}

I run the application and Click on SetView and then on ClearView. Now, in vs diagnostic tools I click on "Take snapshot" And this is the result:

内存快照

Thanks for any help.

I think you should reset simpleview.DataContext when content control is unloaded.

You can do

simpleview.Unloaded += (_, __) => simpleview.DataContext = null;

when SetView .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM