views:

26500

answers:

4

I'm trying to bind a list of custom objects to a WPF Image like this:

<Image>
    <Image.Source>
        <BitmapImage UriSource="{Binding Path=ImagePath}" />
    </Image.Source>
</Image>

But it doesn't work. This is the error I'm getting:

"Property 'UriSource' or property 'StreamSource' must be set."

What am I missing?

+3  A: 

You need to have an implementation of IValueConverter interface that converts the uri into an image. Your Convert implementation of IValueConverter will look something like this:

BitmapImage image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri(value as string);
image.EndInit();

return image;

Then you will need to use the converter in your binding:

<Image>
    <Image.Source>
        <BitmapImage UriSource="{Binding Path=ImagePath, Converter=...}" />
    </Image.Source>
</Image>
Dale Ragan
+6  A: 

You can also simply set the Source attribute rather than using the child elements. To do this your class needs to return the image as a Bitmap Image. Here is an example of one way I've done it

<Image Width="90" Height="90" 
       Source="{Binding Path=ImageSource}"
       Margin="0,0,0,5" />

And the class property is simply this

public object ImageSource {
    get {
        BitmapImage image = new BitmapImage();

        try {
            image.BeginInit();
            image.CacheOption = BitmapCacheOption.OnLoad;
            image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
            image.UriSource = new Uri( FullPath, UriKind.Absolute );
            image.EndInit();
        }
        catch{
            return DependencyProperty.UnsetValue;
        }

        return image;
    }
}

I suppose it may be a little more work than the value converter, but it is another option.

palehorse
A similar implementation to this is perfect for when your bitmap resource is already loaded into your object and you want to pass the bits to the binding. THANKS!
Scott Fletcher
Good point Scott!
palehorse
+12  A: 

BitmapImage UriSource is a stream, i think, and there isn't a built in converter for it.

WPF has built in converters for certain common bindings. If you bind the Image's Source to a string value, underneath the hood WPF will use a value converter to convert the string to a URI, and get the BitmapImage from that.

So if instead you did this:

<Image Source="{Binding ImageSource}" />

It would work (if the ImageSource property was a string representation of a valid uri to an image)

You can of course roll your own, and in Silverlight you need to because of issues the Image control has with Bindings:

public sealed class ImageConverter : IValueConverter
{
    public object Convert(object value, Type targetType,
                          object parameter, CultureInfo culture)
    {
        try
        {
            return new BitmapImage(new Uri((string)value));
        }
        catch 
        {
            return new BitmapImage();
        }
    }

    public object ConvertBack(object value, Type targetType,
                              object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
Brian Leahy
+7  A: 

This article by Atul Gupta has sample code that covers several scenarios:

  1. Regular resource image binding to Source property in XAML
  2. Binding resource image, but from code behind
  3. Binding resource image in code behind by using Application.GetResourceStream
  4. Loading image from file path via memory stream (same is applicable when loading blog image data from database)
  5. Loading image from file path, but by using binding to a file path Property
  6. Binding image data to a user control which internally has image control via dependency property
  7. Same as point 5, but also ensuring that the file doesn't get's locked on hard-disk
Drew Noakes
+1, that was a useful article.
slugster