如何在WPF的代码后台中从Properties.Resources中动态更改图像源?

10
我有一个需要向用户提供内部状态反馈的WPF应用程序。设计是使用三个图片,分别称为红色、黄色和绿色。根据状态只会显示其中之一。以下是要点:
  • 三个图片都在代码后台的Properties.Resources中。
  • 每次只显示其中一个图片。
  • 状态更改来自于代码后台的过程,而不是用户。
  • 我想绑定一个图片控件,以便可以从代码后台更改图片。

我认为我需要一个图片转换器来将JPG图像更改为图片源,例如:


[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();
    }
}

我希望在初始化期间仅转换图像一次,并保留图像源的列表。我还假设我需要一个依赖属性来绑定控件,但我不确定如何使用这个图像源列表设置它:


    // 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); }
    }
1个回答

33
尽管WPF项目中的图像资源在Resources.Designer.cs中生成一个System.Drawing.Bitmap属性,但您可以直接从该资源创建BitmapImage。 您只需要将图像文件的Build Action设置为Resource(而不是默认值None)即可。
如果您在Visual Studio项目的Resources文件夹中有一个名为Red.jpg的文件,则创建BitmapImage将如下所示。 它使用了一个WPF Pack Uri
var uri = new Uri("pack://application:,,,/Resources/Red.jpg");
var bitmap = new BitmapImage(uri);

如果您在XAML中声明了一个Image控件,如下所示:
<Image x:Name="image"/>

你可以在代码后台将图片的Source属性简单地设置为你的BitmapImage:
image.Source = bitmap;

如果您喜欢通过绑定来设置“Source”属性,则可以创建一个返回图像URI的字符串属性。在WPF中,内置的TypeConverter将自动将字符串转换为BitmapImage。请注意保留HTML标签。
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); }
    }
}

在XAML中,您可以像这样绑定到该属性:

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

当然,你也可以将属性声明为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); }
}

并以相同的方式绑定:

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

现在您可以预加载图片并根据需要将它们放入属性中:
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;

更新:实际上,您的图像不需要成为Visual Studio项目中的资源。您可以只添加一个项目文件夹,将图像文件放入该文件夹并将其构建操作设置为Resource。例如,如果您将文件夹命名为Images,则URI将为pack://application:,,,/Images/Red.jpg


Clemens 你太棒了!这是一个非常好的、全面的、易于理解的回答。我很想使用绑定选项,但在我的情况下,在代码后台设置源的第一种选项太优雅了。 唯一的问题是我无法让它与png文件一起工作。我希望有一个透明的背景。它应该可以与png文件一起工作吗?我是做错了什么,还是它们不被支持? - dtaylor
这也适用于PNG文件。也许你不应该将它们添加为项目资源(请参见我的编辑)。只需使用您喜欢的图像工具创建文件并将其添加到项目中的文件夹中即可。有关接受的信息,请参见此处 - Clemens
Clemens,你再次提供了清晰简洁的答案!当我将PNG文件简单地放在一个文件夹中并将其作为资源而不是将其添加为资源设计器中的属性资源时,它运行良好。非常感谢。 - dtaylor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接