【问题标题】:WPF ListView not caching imagesWPF ListView 不缓存图像
【发布时间】:2018-08-08 21:58:48
【问题描述】:

我有一个 WPF 应用程序,它使用 ListView 和一个直接显示来自网络的图像的网格。填充列表后,图像按预期加载,但当我向下滚动时(列表平均包含大约 200 个项目),它开始重用不在视图中的项目(应该如此)。但是,这会导致图像从内存中释放,因此当用户向上滚动时它们会重新加载。

MainWindow.xaml

<ListView Grid.Row="3" ItemsSource="{Binding SearchResults}" Background="{StaticResource PrimaryBackground}" Foreground="{StaticResource PrimaryForeground}"
              ui:GridViewSort.AutoSort="True" ui:GridViewSort.ShowSortGlyph="False" IsSynchronizedWithCurrentItem="True" VirtualizingStackPanel.IsVirtualizing="False">
            <ListView.View>
                <GridView>
                    <GridViewColumn Width="80">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate DataType="{x:Type Foo}">
                                <Image>
                                    <Image.Source>
                                        <BitmapImage CacheOption="OnDemand" UriSource="{Binding PreviewImageUrl}" />
                                    </Image.Source>
                                </Image>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Title" DisplayMemberBinding="{Binding Title}" ui:GridViewSort.PropertyName="Title" />
                    <GridViewColumn Header="Remix" DisplayMemberBinding="{Binding Remix}" ui:GridViewSort.PropertyName="Remix" />
                    <GridViewColumn Header="Artist" DisplayMemberBinding="{Binding Artist}" ui:GridViewSort.PropertyName="Artist" />
                    <GridViewColumn Header="Duration" DisplayMemberBinding="{Binding Duration}" ui:GridViewSort.PropertyName="Duration" />
                    <GridViewColumn Header="BPM" DisplayMemberBinding="{Binding Bpm}" ui:GridViewSort.PropertyName="Bpm" />
                    <GridViewColumn Header="Year" DisplayMemberBinding="{Binding Date}" ui:GridViewSort.PropertyName="Date" />
                    <GridViewColumn>
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal">
                                    <StackPanel.Resources>
                                        <Style TargetType="Button">
                                            <Setter Property="Margin" Value="0,0,10,0" />
                                        </Style>
                                    </StackPanel.Resources>
                                    <Button Command="{Binding ElementName=Window, Path=DataContext.Download}" CommandParameter="{Binding}">Download</Button>
                                    <Button Command="{Binding ElementName=Window, Path=DataContext.CopyLink}" CommandParameter="{Binding}">Copy link</Button>
                                </StackPanel>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>
</ListView>

用不同的CacheOption 设置Image.Source 属性没有区别。您还可以看到我禁用了虚拟化,这很糟糕,但这是将图像保存在内存中的唯一方法。有没有一种简单的方法可以在启用虚拟化的同时阻止这种情况发生?

【问题讨论】:

  • 您需要自己处理图像,没有开箱即用的功能,或者至少我不知道。所以也许你可以改变你的模型并预先下载图像并将它们存储在你的模型对象中,然后你不需要处理任何事情。您将在内存中保存您的图像。

标签: c# wpf


【解决方案1】:

将只读的PreviewImage 属性添加到您的搜索结果项类中,该属性会在首次访问时创建并保存 BitmapImage:

public class SearchResult : INotifyPropertyChanged
{
    private Uri previewImageUrl;
    public Uri PreviewImageUrl
    {
        get { return previewImageUrl; }
        set
        {
            previewImageUrl = value;
            previewImage = null;

            NotifyPropertyChanged(nameof(PreviewImageUrl));
            NotifyPropertyChanged(nameof(PreviewImage));
        }
    }

    private ImageSource previewImage;
    public ImageSource PreviewImage
    {
        get
        {
            if (previewImage == null && previewImageUrl != null)
            {
                previewImage = new BitmapImage(previewImageUrl);
            }

            return previewImage;
        }
    }

    ...
}

并像这样绑定到它:

<GridViewColumn.CellTemplate>
    <DataTemplate>
        <Image Source="{Binding PreviewImage}"/>
    </DataTemplate>
</GridViewColumn.CellTemplate>

【讨论】:

    【解决方案2】:

    试试这个:

    <Image 
        HorizontalOptions="CenterAndExpand"
        VerticalOptions ="CenterAndExpand">
        <Image.Source>
            <UriImageSource Uri="{Binding Image}" 
                CacheValidity="14" 
                CachingEnabled="true"/>
        </Image.Source>
    </Image>
    

    【讨论】:

    • 这在 WPF 中不可用。
    猜你喜欢
    • 1970-01-01
    • 2022-09-27
    • 2019-01-13
    • 2011-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-26
    相关资源
    最近更新 更多