ti-enxame.com

Como altero uma fonte de imagem dinamicamente do code-behind no WPF com uma imagem em Properties.Resources?

Eu tenho um aplicativo WPF que precisa fornecer feedback ao usuário sobre um estado interno. O design é ter três imagens, chamá-las de vermelho, amarelo e verde. Uma dessas imagens será exibida por vez, dependendo do estado. Aqui estão os pontos:

  • As três imagens estão em Properties.Resources no code-behind
  • Apenas uma das imagens será exibida por vez.
  • A mudança de estado vem de um processo no code-behind e não do usuário.
  • Gostaria de vincular um controle de imagem para poder alterar a imagem do code-behind.

Suponho que preciso de um conversor de imagem para alterar a imagem JPG para uma fonte de imagem, 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();
    }
}

Prefiro converter as imagens uma vez durante a inicialização e manter uma lista de fontes de imagem. Também estou assumindo que precisarei de uma propriedade de dependência para vincular o controle, mas não sei como configurá-lo com esta lista de fontes de imagem:


    // 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); }
    }
8
dtaylor

Embora um recurso de imagem em um projeto WPF gere um System.Drawing.Bitmap propriedade em Resources.Designer.cs, você pode criar diretamente um BitmapImage a partir desse recurso. Você só precisa definir o Build Action do arquivo de imagem como Resource (em vez do padrão None).

Se você tiver um arquivo Red.jpg na pasta Resources do seu projeto do Visual Studio, criar um BitmapImage seria como mostrado abaixo. Ele usa um WPF Pack Uri .

var uri = new Uri("pack://application:,,,/Resources/Red.jpg");
var bitmap = new BitmapImage(uri);

Se você tiver um controle Image declarado em algum lugar no XAML como este:

<Image x:Name="image"/>

você pode simplesmente definir a propriedade Source da imagem como sua BitmapImage no código a seguir:

image.Source = bitmap;

Caso você prefira definir a propriedade Source vinculando, você poderá criar uma propriedade string que retorne o URI da imagem. A string será automaticamente convertida em BitmapImage por um interno TypeConverter no 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); }
    }
}

No XAML, você vincularia a essa propriedade assim:

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

É claro que você também pode declarar que a propriedade é do tipo 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); }
}

e vincular da mesma maneira:

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

Agora você pode pré-carregar suas imagens e colocá-las na propriedade, conforme necessário:

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;

ATUALIZAÇÃO: Afinal, suas imagens não precisam ser recursos no projeto Visual Studio. Você pode simplesmente adicionar uma pasta do projeto, colocar os arquivos de imagem nessa pasta e definir a ação de compilação para Resource. Se, por exemplo, você chamar a pasta Images, o URI seria pack://application:,,,/Images/Red.jpg.

32
Clemens