删除以前在WinRT中的DataTemplate中使用的图像文件时拒绝访问

时间:2012-12-05 07:44:28

标签: xaml windows-runtime datatemplate winrt-xaml storagefile

我的GridView使用的图像(PNG)文件是其DataTemplate的一部分。如果我尝试删除GridView中的特定对象行,我也会删除该行的相关图像文件。列表中的每个项目的图像都不同。

我正在使用此代码删除图片文件

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

图像文件在GridView的DataTemplate下的GridView上呈现。 所以在我的List中的每个对象模型中,我都有一个公共属性,它为我的DataTemplate返回一个ImageSource。

我在从List中删除了对象行并且在刷新了新的List项之后立即调用了我的删除过程。

即使List不再包含对象(使用图像),如果我尝试删除文件,应用程序也会抛出Access is Denied异常。当应用程序运行时,如果我尝试手动删除该特定文件(通过文件浏览器),它也不允许我。

我尝试清除应用中的所有未使用的对象,甚至在删除图像之前将GridView的ItemSource设置为null并将List设置为null。仍然存在例外情况。

提前致谢。

5 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

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

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

现在实际解决方案:

将Image.Source设置为null在此处不起作用,因为URI仍处于活动状态(至少在下一个GC循环之前)。 DID对我有用,将Source转换为它最初的BitmapImage,并将UriSource设置为null。

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

是的,这是愚蠢的。

答案 2 :(得分:0)

诀窍是使用Uri对象加载图像(而不是字符串文件名),然后使用EXACT相同的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();

答案 3 :(得分:0)

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

答案 4 :(得分:0)

Mark已经提到了其中的一部分,但是没有必要使其变得如此复杂。简而言之,只要您希望在系统保留该位图的同时需要删除该位图,就可以使用如下转换器:

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与流一起使用,系统将需要该流,因此您不应该及早处置它。