• Download images and store them in isolated storage (Windows Phone 7 and 8)

    For my windows phone app I need to retrieve some images from the internet. Windows Phone automatically caches them as long as the application is alive, but as soon as the application is stopped and restarted the cache is gone and images need to be retrieved again. I’ve found several proposals (e.g. One-time Cached Images in Windows Phone 7 or the extended version “Intelligent” Image Caching for WP 7) next to Image Tips for Windows Phone 7 and App performance considerations for Windows Phone but in the end I setup a solution based on Displaying an Image from Isolated Storage and Off-thread decoding of images on Mango The solution below is in vb.net for Windows Phone 7.1 (and Windows Phone 8 of course) and processes like this:

    1. Check whether the requested image is available in isolated storage. If so, display image from there.
    2. If not, download image in the background and display it to the user.
    3. After downloading save it to isolated storage.

    The solution has the following advantages:

    1. Images are only load once.
    2. Images are loaded in the background.
    3. Easy to implement.
    4. Works fine also in a listbox with multiple images on the screen.

     

    Implementation

    New Class

    First create a new class called ‘ImageCacheConverter.vb’ and add the following code:

    Imports System.Windows.Data
    Imports System.Windows.Media.Imaging
    Imports System.IO

    Public Class imageCacheConverter
    Implements IValueConverter

    Private Shared ISF As IsolatedStorage.IsolatedStorageFile = IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication()

    ”’ <param name=”value”>Contains a path to the internet file, e.g. https://dotnetco.de/myimagefile.png</param>
    Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.Convert
    Dim path As String = TryCast(value, String)
    Dim filename As String
    If [String].IsNullOrEmpty(path) Then
    Return Nothing
    ElseIf path.Contains(“/”) Then
    filename = System.IO.Path.GetFileName(path)
    Else
    filename = path
    End If
    If ISF.FileExists(filename) Then
    Using sourceFile As IO.Stream = ISF.OpenFile(filename, FileMode.Open, FileAccess.Read)
    Dim bm As New BitmapImage()
    bm.SetSource(sourceFile)
    Return bm
    End Using
    Else
    Dim source As New BitmapImage(New Uri(path, UriKind.Absolute))
    source.CreateOptions = BitmapCreateOptions.BackgroundCreation
    AddHandler source.ImageOpened, Sub(sender, e) SaveImageToISOAfterDownload(sender, e, filename)
    Return source
    End If
    End Function

    Private Sub SaveImageToISOAfterDownload(sender As Object, e As System.Windows.RoutedEventArgs, filename As String)
    If Not ISF.FileExists(filename) Then
    Dim bitmap As New WriteableBitmap(CType(sender, BitmapSource))
    bitmap.SaveJpeg(ISF.CreateFile(filename), bitmap.PixelWidth, bitmap.PixelHeight, 0, 100)
    End If
    End Sub

    Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
    Throw New NotImplementedException()
    End Function

    End Class

    So in ‘Convert’ we first check whether the file exists in isolated storage. If so, the bitmap is returned. Otherwise the bitmap is retrieved from the given internet address. Additionally we set a handler to be executed as soon as the image is retrieved completely (AddHandler source.ImageOpened) and supply the filename so we could save the file later on. (As seen I save all images into the root directory of the isolated storage). That’s it for the programming part.

    App.xaml

    In App.xaml we first add the namespace (if not already done)

    <Application (…) xmlns:local=”clr-namespace:MyNamespace”> 

    and add the converter to Application Resources

    <Application.Resources>
    <local:imageCacheConverter x:Key=”imageCacheConverter”></local:imageCacheConverter>
    </Application.Resources>

    Mainpage.xaml

    So now in the MainPage.xaml we could use the image this way:

    <Image Name=”MyIcon” Source=”{Binding ImageFilename, Converter={StaticResource imageCacheConverter}}” />    

     Done

    So that’s it. Now you could retrieve your images only once and reuse them as long as your application is installed. No need again for an internet connection.

Leave a comment

If you want to share your opinion, leave a comment.

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">