0 Comments

Update 17.7.2012:

As Kyle Burns pointed out, these workaround are no longer necessary. "as of the Release Candidate because directly setting the Source property with a Uri works as expected."

Problem

In Windows Phone 7 it’s possible to bind Image-control’s Source-property to either to a string or to an Uri and they both work. In WinRT binding against an Uri doesn’t work.

Given the following XAML:

<ListBox x:Name="Items">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Image Width="500" Height="500" Source="{Binding Image}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

And the following view model:

public class ItemVM
    {
        public string Image { get; set; }
        public string Title { get; set; }
        public string Subtitle { get; set; }
    }

imageThe image is displayed correctly in WinRT. But if the view model contains an Uri instead of a string, the image isn’t displayed.

public class ItemVM
    {
        public Uri Image { get; set; }
        public string Title { get; set; }
        public string Subtitle { get; set; }
    }

This can be problematic if you want to share your VMs between different platforms.

One possible solution

If you need to get the binding against an Uri to work you can create the following value converter:

public class ImageUriValueConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            var uri = value as Uri;
            if (uri == null)
                return null;

            var result = uri.ToString();
            return result;
        }

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

And use that in your binding:

<Page.Resources>
        <local:ImageUriValueConverter x:Name="Converter"/>
    </Page.Resources>
    
    <Grid Background="{StaticResource ApplicationPageBackgroundBrush}">
        <ListBox x:Name="Items">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Image Width="500" Height="500" Source="{Binding Image, Converter={StaticResource Converter}}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>

Another possible solution

This sounds like an beta-issue which could be very well fixed in the final release.

Update 5.2.2012

Morten posted a great tip in the comments. For some reason the blog doesn't allow me to approve it, so here's his whole comment:

Try this instead: 
<Image> 
    <Image.Source> 
         <BitmapImage UriSource="{Binding ImageUri}" /> 
   </Image.Source> 
</Image> 
   
This avoids all the converter code, and also allows you to be more specific on your BitmapImage wrt CreationOptions, DecodePixelSize etc. (however with a converter let me suggest you convert to a BitmapImage instead of string, or you'll just hit more converters when processing the binding)