¿Cómo cambio dinámicamente la fuente de una imagen desde el código subyacente en WPF con una imagen en Properties.Resources?
Tengo una aplicación WPF que necesita proporcionar comentarios al usuario sobre un estado interno. El diseño debe tener tres imágenes, llámelas Roja, Amarilla y Verde. Una de estas imágenes se mostrará a la vez dependiendo del estado. Aquí están los puntos:
- Las tres imágenes están en Propiedades. Recursos en el código subyacente.
- Sólo se mostrará una de las imágenes a la vez.
- El cambio de estado proviene de un proceso de código subyacente y no del usuario.
- Me gustaría vincular un control de imagen para poder cambiar la imagen desde el código subyacente.
Supongo que necesitaré un convertidor de imágenes para cambiar la imagen JPG a una fuente de imagen como:
[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();
}
}
Preferiría convertir las imágenes una vez durante la inicialización y mantener una lista de fuentes de imágenes. También supongo que necesitaré una propiedad de dependencia para vincular el control, pero no estoy seguro de cómo configurarla con esta lista de fuentes de imágenes:
// 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); }
}
Aunque un recurso de imagen en un proyecto WPF genera una System.Drawing.Bitmap
propiedad en Resources.Designer.cs
, puedes crear una directamente BitmapImage
a partir de ese recurso. Solo necesita configurar la Acción de compilación del archivo de imagen en Resource
(en lugar del valor predeterminado None
).
Si tiene un archivo Red.jpg
en la Resources
carpeta de su proyecto de Visual Studio, crearlo BitmapImage
se vería como se muestra a continuación. Utiliza un paquete Uri de WPF .
var uri = new Uri("pack://application:,,,/Resources/Red.jpg");
var bitmap = new BitmapImage(uri);
Si tiene un Image
control declarado en algún lugar de XAML como este:
<Image x:Name="image"/>
simplemente puede establecer la Source
propiedad de la imagen en su BitmapImage en el código subyacente:
image.Source = bitmap;
En caso de que prefiera establecer la Source
propiedad mediante enlace, puede crear una string
propiedad que devuelva el URI de la imagen. La cadena se convertirá automáticamente en BitmapImage
una función integrada TypeConverter
en 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); }
}
}
En XAML te vincularías a esa propiedad de esta manera:
<Image Source="{Binding ImageUri}"/>
Por supuesto, también podrías declarar que la propiedad es del tipoImageSource
public static readonly DependencyProperty ImageProperty =
DependencyProperty.Register("Image", typeof(ImageSource), typeof(MainWindow));
public ImageSource Image
{
get { return (ImageSource)GetValue(ImageProperty); }
set { SetValue(ImageProperty, value); }
}
y unir de la misma manera:
<Image Source="{Binding Image}"/>
Ahora puedes precargar tus imágenes y colocarlas en la propiedad según sea necesario:
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;
ACTUALIZACIÓN: Después de todo, sus imágenes no necesitan ser recursos en el proyecto de Visual Studio. Podría simplemente agregar una carpeta de proyecto, colocar los archivos de imagen en esa carpeta y configurar su Acción de compilación en Resource
. Si por ejemplo llamas a la carpeta Images
, el URI sería pack://application:,,,/Images/Red.jpg
.