I have a WPF application that needs to provide feedback to the user about an internal state. The design is to have three images, call them Red, Yellow, and Green. One of these images will be displayed at a time depending on the state. Here are the points:
I’m assuming I’ll need an image converter to change the JPG image to an image source such as:
[ValueConversion(typeof(System.Drawing.Bitmap), typeof(ImageSource))]
public class BitmapToImageSourceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var bmp = value as System.Drawing.Bitmap;
if (bmp == null)
return null;
return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
bmp.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
I’d prefer to convert the images once during initialization and keep a list of Image sources. I’m also assuming I’ll need a dependency property to bind the control to, but I’m not sure how to set that up with this list of image sources:
// Dependancy Property for the North Image
public static readonly DependencyProperty NorthImagePathProperty
= DependencyProperty.Register(
"NorthImagePath",
typeof(ImageSource),
typeof(MainWindow),
new PropertyMetadata("**Don't know what goes here!!!**"));
// Property wrapper for the dependancy property
public ImageSource NorthImagePath
{
get { return (ImageSource)GetValue(NorthImagePathProperty); }
set { SetValue(NorthImagePathProperty, value); }
}
Although an image resource in a WPF project generates a System.Drawing.Bitmap
property in Resources.Designer.cs
, you could directly create a BitmapImage
from that resource. You only need to set the Build Action of the image file to Resource
(instead of the default None
).
If you have a file Red.jpg
in the Resources
folder of your Visual Studio Project, creating a BitmapImage
would look like shown below. It uses a WPF Pack Uri.
var uri = new Uri("pack://application:,,,/Resources/Red.jpg");
var bitmap = new BitmapImage(uri);
If you have an Image
control declared somewhere in XAML like this:
<Image x:Name="image"/>
you could simply set the Source
property of the image to your BitmapImage in code behind:
image.Source = bitmap;
In case you prefer to set the Source
property by binding you could create a string
property that returns the image URI. The string will automatically be converted to a BitmapImage
by a built-in TypeConverter
in WPF.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
ImageUri = "pack://application:,,,/Resources/Red.jpg";
}
public static readonly DependencyProperty ImageUriProperty =
DependencyProperty.Register("ImageUri", typeof(string), typeof(MainWindow));
public string ImageUri
{
get { return (string)GetValue(ImageUriProperty); }
set { SetValue(ImageUriProperty, value); }
}
}
In XAML you would bind to that property like this:
<Image Source="{Binding ImageUri}"/>
Of course you could as well declare the property to be of type ImageSource
public static readonly DependencyProperty ImageProperty =
DependencyProperty.Register("Image", typeof(ImageSource), typeof(MainWindow));
public ImageSource Image
{
get { return (ImageSource)GetValue(ImageProperty); }
set { SetValue(ImageProperty, value); }
}
and bind in the same way:
<Image Source="{Binding Image}"/>
Now you could pre-load your images and put them into the property as needed:
private ImageSource imageRed =
new BitmapImage(new Uri("pack://application:,,,/Resources/Red.jpg"));
private ImageSource imageBlue =
new BitmapImage(new Uri("pack://application:,,,/Resources/Blue.jpg"));
...
Image = imageBlue;
UPDATE: After all, your images do not need to be resources in the Visual Studio project. You could just add a project folder, put the image files into that folder and set their Build Action to Resource
. If for example you call the folder Images
, the URI would be pack://application:,,,/Images/Red.jpg
.