5

注意:通用 Windows 平台(又名 Windows 10 应用程序,不是 WPF)

我有大约 80 个图像文件需要显示在页面内的列表视图上。当用户返回上一页时,我需要处理图像控件,以便我可以删除这些图像。

问题是直接绑定到image uri 锁定了图片文件,返回时没有释放

我正在使用 MVVMLight

一些代码:

public class FileNameToFullUriConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        string ori = value.ToString();
        string file = ori.Split('/').Last();
        string img = file.Split('.')[0] + ".png";
        img = "ms-appdata:///local/" + StaticClass.ImageFolder + "/" + img;

        return img;

    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        return null;
    }
}

和 XAML

<DataTemplate>
    <Grid>
        <Image x:Name="Image2"
               Grid.Column="1"
               HorizontalAlignment="Left"
               Source="{Binding Page2.Page.file,
               Converter={StaticResource FileNameToFullUriConverter},
               Mode=OneWay}"
               Stretch="UniformToFill" />
    </Grid>
</DataTemplate>

我试过了:

  • 将列表设置为空

  • 清除列表(通过调用 ListViewName.Clear() )

  • ViewModelLocator 中的调用清理

什么有效,但不能应用:在 ViewModel 中,我添加了另一个类型为

ObservableCollection<BitmapImage>

,然后将 ListView 绑定到此集合。通过这种方式,所有的图像都会被加载到 RAM 中,不会锁定文件,但它会导致一个严重的问题:消耗过多的 RAM。通过直接绑定到 BitmapImage,我的应用程序使用 URI 绑定占用了大约 100 MB RAM 到 900 MB RAM。此外,加载到页面所需的时间更长,因为它必须在列表完成呈现之前读取所有图像文件并将其加载到 RAM 中。

那么,如何在 Windows 10 中配置 Image Control 呢?

PS:这个图像控件:MSDN中的Image Class

4

3 回答 3

1

您可以在页面后面的代码中维护您的图像控件列表。当应用程序返回时,您可以将每个图像的 Source 属性设置为 null :

<DataTemplate>
    <Grid>
        <Image Loaded="Image_Loaded" />
    </Grid>
</DataTemplate>

在后面的代码中:

private List<Image> _images = new List<Image>();

private void Image_Loaded(object sender, RoutedEventArgs e)
{
    _images.Add(sender as Image);
}

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    base.OnNavigatedFrom(e);
    foreach(var img in _images)
    {
        img.Source = null;
    }
}

所有的锁都会被释放。

于 2015-12-22T09:05:00.220 回答
0

我有同样的问题。我使用了一种解决方法,我不确定这是否是最好的方法。我添加了一个方法来删除已删除的项目,并在每次应用程序启动或列表刷新时调用该方法。

private ObservableCollection<BitmapImage> _items; // your collection which is bound to ListView

// deleting images of removed items
private async Task DeleteUnusedImages()
{
    try
    {
        var folder = await ApplicationData.Current.LocalFolder.GetFolderAsync("folderName");
        var files = await folder.GetFilesAsync(); // getting all files inside that folder

        foreach (var file in files)
        {
            // checking if the image still exist in the collection or got removed
            // if removed then remove it from the local folder too.
            if (!_items.Any(i => i.ImageName.Contains(file.Name)))
            {
                await file.DeleteAsync(StorageDeleteOption.PermanentDelete);
            }
        }
    }
    catch (Exception ex)
    {

    }
}

问题是当您从绑定到 ListView 的集合中删除一个项目时,ListView 直到几次刷新才会释放该项目。删除项目后,我尝试通过转到应用程序的“LocalState”文件夹手动删除它,但它说它已被应用程序使用并且无法删除。

于 2016-08-07T08:24:56.283 回答
0

我对图像控制不是很熟悉。在我看来,必须先处置位图图像,然后才能删除文件。问题是 bitmapImage 没有 Dispose 功能。

我在这里看到其他人在堆栈溢出中询问如何主动处置图像。我想你也必须这样做。

请参阅: 如何处理位图源

删除位图源文件

于 2015-12-21T09:34:19.077 回答