【问题标题】:WPF ListboxItems Cosume too much memoryWPF 列表框项消耗太多内存
【发布时间】:2013-08-12 20:29:29
【问题描述】:

好的,我有一个 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 都会用至少 1000 个StationItems 填充我的ListBox

我的代码运行良好,内存为 40MB(Window 任务管理器)。但是每当我选择一个流派并填充我的ListBox 时,内存会以 100MB 爆炸。然后我选择另一个流派内存会进一步爆炸。我认为ListBox.Items.Clear();ListBoxItems 也会从内存中销毁,但这不会发生。

我试图从我的ListoBoxItemTemplate 中删除图像并检查了我的应用程序的内存,但没有发现真正的差异(大约 4-7 MB 的差异)。

所以我的答案是:在ListBox 中添加项目时,如何让我的应用程序消耗更少的内存?

提前致谢!!

【问题讨论】:

  • 内存泄漏可能在Image 控制。如果您删除它,您是否仍然看到内存有任何显着增长?
  • 当我填充 ListBox 时,我得到了 100MB 的内存分配。如果我从 DataTemplate 中删除图像,我得到的内存分配会少一点,大约 95 MB。
  • 您大约有多少件物品?超过10000?
  • 也许您需要尝试VirtualizationModeVirtualizingStackPanelLink.
  • @AnatoliyNikolaev 成功了完美。我刚刚用&lt;VirtualizingStackPanel VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" Orientation="Horizontal" MaxHeight="220" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Disabled" HorizontalAlignment="Center" VerticalAlignment="Center"/&gt; 替换了我的WrapPanel 并且内存泄漏消失了。也许你应该发布你的答案以便接受它。非常感谢你。

标签: c# wpf memory listbox listboxitems


【解决方案1】:

尝试使用VirtualizingStackPanel.VirtualizationMode="Recycling" 来提高性能。引用MSDN:

默认情况下,VirtualizingStackPanel 会为每个可见项目创建一个项目容器,并在不再需要它时将其丢弃(例如当项目被滚动出视图时)。当 ItemsControl 包含大量项目时,创建和丢弃项目容器的过程会对性能产生负面影响。当 VirtualizingStackPanel.VirtualizationMode 设置为 Recycling 时,VirtualizingStackPanel 会重复使用项目容器,而不是每次都创建一个新容器。

【讨论】:

    猜你喜欢
    • 2020-04-16
    • 2011-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-16
    • 2016-06-29
    • 1970-01-01
    相关资源
    最近更新 更多