Wednesday 19 June 2013

Deleting Images from Storage Displayed in XAML in Windows 8

Overview

It's possible to display images from storage in XAML using the following URI syntax:

Property:

public string StorageName { get { return "ms-appdata:///local/images/image.jpg"; } }

XAML:

<Image Margin="5" Width="50" Height="50" Source="{Binding StorageName}" />

This can be handy in various scenarios, for me it was to keep a scaled-down copy of a users image for efficiency and to make sure it wasn't deleted.

This is fine but a problem can occur if you want to delete the image when it is displayed on the UI as you get a "System.UnautorizedAccessException" like this:


Solution

I couldn't find a way of stopping this exactly when I wanted to delete the image, so I decided to keep a note of images to delete, then delete them when the application launched and the images were no longer in use.

NoteImageForDeletion

Call this when you want to note an image for deletion

private const string NOTED_FOR_DELETION = "NOTED_FOR_DELETION";

public static void NoteImageForDeletion(string name)
{
  try
  {
    List<string> noted = new List<string>();
    if (ApplicationData.Current.LocalSettings.Values.ContainsKey(NOTED_FOR_DELETION))
    {
      noted = new List<string>((string[])ApplicationData.Current.LocalSettings.Values[NOTED_FOR_DELETION]);
    }

    noted.Add(name);

    ApplicationData.Current.LocalSettings.Values[NOTED_FOR_DELETION] = noted.ToArray();
  }
  catch (Exception)
  {
  }

}


DeleteNotedImages

Call this when the app starts

public async static Task DeleteNotedImages()
{
  List<string> noted = new List<string>();
  if (ApplicationData.Current.LocalSettings.Values.ContainsKey(NOTED_FOR_DELETION))
  {
    noted = new List<string>((string[])ApplicationData.Current.LocalSettings.Values[NOTED_FOR_DELETION]);
  }

  foreach (var n in noted)
    await DeleteImage(n);
}

public static async Task DeleteImage(string name)
{
  try
  {
    var folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("images", CreationCollisionOption.OpenIfExists);
    StorageFile file = await folder.GetFileAsync(name);
    await file.DeleteAsync();
  }
  catch (FileNotFoundException)
  {
  }
}

Conclusion

This is a work-around, but a good way of decoupling the image deletion process from the UI.

No comments:

Post a Comment