6

I have image (PNG) files used by my GridView as part of its DataTemplate. If I try to delete a specific object row in my GridView, I would delete the related image file for that row as well. The images are different for every item on the list.

I'm using this code to delete the image file

StorageFile _file = await DataStore.GetFileAsync(filename);
await _file.DeleteAsync(StorageDeleteOption.Default);

The image file is rendered on the GridView under the GridView's DataTemplate. So in each object model in my List, I have a public property there that returns an ImageSource for my DataTemplate.

I'm calling my delete procedure right after i deleted the object row from the List and after the GridView has been refreshed of the new List items.

Even though the List does not contain the object (consuming the image) anymore, the app throws the Access is Denied exception if i try to delete the file. While the app is running, if i try to delete that particular file manually (through file explorer), it won't allow me too.

I tried clearing all unused objects in my app, even setting the GridView's ItemSource to null and the List to null before I delete the image. Still the exception persist.

Thanks in advance.

4

5 回答 5

2

您可以尝试的一种方法是将图像加载到内存流中,然后BitmapImage从该流创建一个对象,然后您可以将Image控件的源设置为该位图图像。

由于您没有使用实际的图像文件作为图像的来源,因此您可以随时轻松删除它:)

于 2013-01-16T05:57:48.387 回答
2

马克已经提到了其中的一部分,但没有必要让它那么复杂。简单地说,无论您希望在系统保留位图时需要删除位图的任何位置,都可以使用如下转换器:

public class SafeImageFileConverter : IValueConverter {
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
    string path = (string)value;
    var stream = new MemoryStream(File.ReadAllBytes(path));
    return ImageSource.FromStream(() => stream);
  }
}

在实践中,您可能想要检查路径是否存在,error.png如果不存在则返回或类似。此外,不要试图using与流一起使用,系统将需要流,因此您不应该提前处理它。

于 2018-07-01T15:49:30.743 回答
1

虽然这是一个老问题,但我最近在 UWP 应用程序中遇到了这个问题,并且实际上设法找到了解决方案。但首先是有关该问题的一些背景信息:

当您使用 URI 创建 BitmapImage 时,创建的 URI 对象包含对本地存储中文件的引用并保持打开状态,即不可写。顺便说一句,仅当位图足够大以完全适合图像时才适用,通常是小型或中型位图。如果位图恰好足够大,WinRT 会在图像中显示时自动使用下采样版本。在这种情况下,URI 不包含对原始文件的引用。

现在到实际的解决方案:

将 Image.Source 设置为 null 在这里不起作用,因为 URI 仍然存在(至少直到下一个 GC 周期)。对我有用的是,将 Source 转换为原来的 BitmapImage 并将 UriSource 设置为 null。

var bitmapImage = image.Source as BitmapImage;
if (bitmapImage != null)
  bitmapImage.UriSource = null;

是的,这很愚蠢。

于 2016-02-01T18:23:45.907 回答
0

诀窍是使用 Uri 对象来加载图像(而不是字符串文件名),然后使用完全相同的 Uri 实例来删除文件(当然是在从 UI 中删除图像之后)。这是一个例子:

//Save the Uri as a member variable so you can get to it later
private Uri uri;

//Create the Uri
uri = new Uri(OriginalImageFilename, UriKind.Absolute);

//Load the image
BitmapImage bitmapImage = new BitmapImage(uri);
//This can also be done by binding a Image control's source property to the uri.

//Delete the image (remember to use the same Uri instance)
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(uri);
await file.DeleteAsync();
于 2012-12-30T19:50:26.747 回答
0

作为一种解决方法,我只是在应用程序启动期间删除了未使用的图像,以便没有进程正在使用它。谢谢。

于 2013-01-16T05:45:18.887 回答