MVVM placeholder images for failed image load on Windows Phone 7 with Caliburn Micro

02 June 2011

When using the Image control in Windows Phone 7 and pointing to an unknown url, we have to be mindful of the fact that the url might not be a valid url. In this instance it’s advisable to display some sort of default placeholder image instead so that there is not a blank area in our UI.

First of all, let’s make sure we store our placeholder image reference within App.xaml. Make sure this image file’s Build Action is set to Content (a good practice for all your image files to avoid xap bloat).

 <BitmapImage x:Key="ImagePlaceholder" UriSource="/Resources/Images/Placeholders/Thumb.png" />

Now let’s look at the Image View xaml. Notice we are using an interaction trigger to bind the ImageFailed event from the Image to a ThumbImageFailed method on our View Model (all done using a Caliburn Micro Action Message). Note also the Converter which is used to bind a string url value to the Source property of the image.

The scenario here would be urls given to you from some sort of feed or web service which you are automatically binding to a list.

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"  
xmlns:cm="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"

<Image x:Name="ThumbImage"  Source="{Binding ImageThumbUrl, Converter={StaticResource ImageBindConverter}}" >
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="ImageFailed">
            <cm:ActionMessage MethodName="ThumbImageFailed">
                <cm:Parameter Value="$source" />
            </cm:ActionMessage>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Image>

The ImageBindConverter converter class below tries to generate a BitmapImage from a string value. In this case of a malformed uri, an exception will be thrown and in this instance we return our placeholder image.

public class ImageBindConverter : IValueConverter
{
    public object Convert(
        object value,
        Type targetType,
        object parameter,
        CultureInfo culture)
    {
        try
        {
            return new BitmapImage(new Uri(value.ToString(), UriKind.Absolute));
        }
        catch
        {
                return App.Current.Resources["ImagePlaceholder"] as BitmapImage;
        }
    }

    public object ConvertBack(
        object value,
        Type targetType,
        object parameter,
        CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Assuming the uri is validly constructed, then the image will load successfully or the ThumbImageFailed method will fire in our View Model (via the ImageFailed event on the Image itself) to indicate that the image has not loaded correctly. Again in this instance we simply set the Image source as our thumbnail image resource.

public void ThumbImageFailed(Image image)
{
    image.Source = App.Current.Resources["ImagePlaceholder"] as BitmapImage;
}

In summary, this seems like a good recipe to deal with loading images from the web in a defensive way that adheres to MVVM patterns on Windows Phone 7.

Want to get started?

We would love to help with your next app or game, please do get in touch.