¿Cómo cambio dinámicamente la fuente de una imagen desde el código subyacente en WPF con una imagen en Properties.Resources?

Resuelto dtaylor asked hace 11 años • 1 respuestas

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); }
    }
dtaylor avatar Feb 21 '13 22:02 dtaylor
Aceptado

Aunque un recurso de imagen en un proyecto WPF genera una System.Drawing.Bitmappropiedad en Resources.Designer.cs, puedes crear una directamente BitmapImagea 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.jpgen la Resourcescarpeta de su proyecto de Visual Studio, crearlo BitmapImagese 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 Imagecontrol declarado en algún lugar de XAML como este:

<Image x:Name="image"/>

simplemente puede establecer la Sourcepropiedad de la imagen en su BitmapImage en el código subyacente:

image.Source = bitmap;

En caso de que prefiera establecer la Sourcepropiedad mediante enlace, puede crear una stringpropiedad que devuelva el URI de la imagen. La cadena se convertirá automáticamente en BitmapImageuna función integrada TypeConverteren 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.

Clemens avatar Feb 21 '2013 17:02 Clemens