Databinding a System.Drawing.Image into a WPF System.Windows.Image

I’m learning WPF, very slowly, as a background thing.

I’m working very slowly through some WPF at the moment, and discovered something I thought was really odd. The classic .Net Image class — System.Drawing.Image — can’t be easily databound into the WPF Image control.

That seemed crazy to me — it’s like having a `PictureBox` control without an `Image` property. I resolved to fix it in the most ‘WPFy’ way I could.

What I’d tried was binding a ListView to a list of objects, like so;

Id bound to an object which declares two properties;

string DisplayName { get; }
System.Drawing.Image Image { get; set; }

I wanted to populate a `DataTemplate` but if I did this in my template;

The text appears but the image does not. It turns out that WPF can’t find a suitable converter.

So, thanks to [Reed Copsey](http://reedcopsey.com/) and his very helpful [pointer on Stack Overflow](http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/833ca60f-6a11-4836-bb2b-ef779dfe3ff0/), and [this tutorial](http://www.switchonthecode.com/tutorials/wpf-tutorial-binding-converters), I’ve found a way I’m happy with; one that doesn’t involve c# code-behind.

I’ve created an `IValueConverter` which does the conversion from `System.Drawing.Image` to `System.Windows.Media.ImageSource`. A big thank-you to [Matt Galbraith of Microsoft](http://social.msdn.microsoft.com/profile/matt%20galbraith%20-%20msft) for providing the core code;

using System;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Windows.Data;

namespace System.Windows.Media
{
///

/// One-way converter from System.Drawing.Image to System.Windows.Media.ImageSource
///

[ValueConversion(typeof(System.Drawing.Image), typeof(System.Windows.Media.ImageSource))]
public class ImageConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
// empty images are empty…
if (value == null) { return null; }

var image = (System.Drawing.Image)value;
// Winforms Image we want to get the WPF Image from…
var bitmap = new System.Windows.Media.Imaging.BitmapImage();
bitmap.BeginInit();
MemoryStream memoryStream = new MemoryStream();
// Save to a memory stream…
image.Save(memoryStream, image.RawFormat);
// Rewind the stream…
memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
bitmap.StreamSource = memoryStream;
bitmap.EndInit();
return bitmap;
}

public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
return null;
}
}
}

Then you need to bring the image converter into XAML as a resource. Add the namespace declaration to the window;

xmlns:med=”clr-namespace:System.Windows.Media”

Stick an instance of the `ImageConverter` into a static resource;

Then you can use it in XAML to bind directly to the Image, using the new converter;

So. A re-usable converter which allows databinding directly to GDI image objects.

Originally discussed [on stack overflow](http://stackoverflow.com/questions/3427034/using-xaml-to-bind-to-a-system-drawing-image-into-a-system-windows-image-control)

Advertisement

11 responses to “Databinding a System.Drawing.Image into a WPF System.Windows.Image”

  1. I tried this, and my images, which have a transparent background, are now displayed with a black background.

  2. To preserve all features of the original image, I think you should replace

    image.Save(memoryStream, ImageFormat.Bmp);

    with

    image.Save(memoryStream, image.RawFormat);

    By doing this, you’ll keep features like transparency/alpha channels from image formats like PNG.

%d bloggers like this: