WPF ListboxItems Cosume слишком много памяти

Хорошо, у меня есть приложение WPF, в котором я создаю свое собственное ListBoxItem в словаре ресурсов, который выглядит следующим образом:

    <DataTemplate x:Key="StationItem">
    <Grid x:Name="Gridder" Tag="{Binding SItem.StationName}" Width="125" Height="55">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="20"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="20"/>
        </Grid.ColumnDefinitions>
        <Rectangle x:Name="Rectagler" Width="120" Height="50" RadiusX="5" RadiusY="5" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.ColumnSpan="2" Grid.RowSpan="2" StrokeThickness="1" Stroke="Black">
            <Rectangle.Fill>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FFFF3A00" Offset="0"/>
                    <GradientStop Color="#FFE88D20" Offset="1"/>
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <TextBlock Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" x:Name="StationName" Text="{Binding SItem.StationName}" Foreground="Black" FontSize="14" FontWeight="SemiBold" TextWrapping="NoWrap" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0"/>
        <TextBlock Grid.Column="0" Grid.Row="1" x:Name="StationCountry" Text="{Binding SItem.StationCountry}" Foreground="WhiteSmoke" FontSize="11" FontWeight="Light" TextWrapping="NoWrap" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,8"/>
        <Image Tag="{Binding SItem.StationName}" Width="15" Height="15" RenderOptions.BitmapScalingMode="HighQuality" Grid.Column="1" Grid.Row="1" Source="{Binding FavSource}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,10,10"/>
    </Grid>
    <DataTemplate.Triggers>
        <Trigger Property="IsMouseOver" Value="true">
            <Setter TargetName="Rectagler" Property="Width" Value="125"/>
            <Setter TargetName="Rectagler" Property="Height" Value="55"/>
            <Setter TargetName="StationName" Property="Foreground" Value="White"/>
        </Trigger>
    </DataTemplate.Triggers>
</DataTemplate>

ListBox как это:

        <ListBox x:Name="StationsListLB" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="5" ItemTemplate="{DynamicResource GenreStyle}" ItemContainerStyle="{DynamicResource ContainerStyle}" Background="{x:Null}" BorderBrush="{x:Null}" PreviewMouseLeftButtonDown="StationsListLB_PreviewMouseLeftButtonDown" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Disabled" PreviewMouseDoubleClick="StationsListLB_PreviewMouseDoubleClick">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel IsItemsHost="True" Orientation="Vertical" MaxHeight="220" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Disabled" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>

И я заполняю свой ListBox элементы, когда пользователь выбирает жанр станции, с помощью метода, подобного этому:

 public class Stations
{
    public StationItem SItem { get; set; }
    public string FavSource { get; set; }
}

public class StationItem
{
    public string StationName { get; set; }
    public string StationUrl { get; set; }
    public string StationGenre { get; set; }
    public string StationWebsite { get; set; }
    public string StationCountry { get; set; }
}

    private void LoadStationByGenre(string Genre)
    {
        StationsListLB.Items.Clear();
        StationsListLB.ItemTemplate = (DataTemplate)FindResource("StationItem");

        IEnumerable<Stations> results = StationList.Where(s => s.SItem.StationGenre.Equals(Genre));

        foreach (var Station in results)
        {
            StationsListLB.Items.Add(Station);
        }
    }

Примечание: каждый StationGenre будет заполнять мой ListBox по крайней мере 1000 StationItems ,

Мой код работает нормально и начинается с памяти 40 МБ (Window Task Manager). Но всякий раз, когда я выбираю жанр и заполняю свой ListBox, память взрывается со скоростью 100 МБ. И затем я выбираю другой жанр, память взрывается дальше. Я думал, что с ListBox.Items.Clear(); ListBoxItems будет также уничтожен из памяти, но этого не произойдет.

Я пытался удалить изображение из моего ListoBoxItemTemplate и проверил память моего приложения, но не увидел реальной разницы (разница около 4-7 МБ).

Итак, мой ответ: как я могу заставить мое приложение потреблять намного меньше памяти при добавлении элементов в ListBox?

Заранее спасибо!!

1 ответ

Решение

Попробуй использовать VirtualizingStackPanel.VirtualizationMode="Recycling" улучшить производительность. Цитата из MSDN:

По умолчанию VirtualizingStackPanel создает контейнер элемента для каждого видимого элемента и удаляет его, когда он больше не нужен (например, когда элемент прокручивается вне поля зрения). Когда ItemsControl содержит много элементов, процесс создания и удаления контейнеров элементов может отрицательно повлиять на производительность. Когда для VirtualizingStackPanel.VirtualizationMode установлено значение "Переработка", VirtualizingStackPanel повторно использует контейнеры элементов вместо того, чтобы каждый раз создавать новый.

Другие вопросы по тегам