web-dev-qa-db-ja.com

Properties.Resourcesの画像を使用して、WPFのコードビハインドから画像ソースを動的に変更するにはどうすればよいですか?

内部状態についてユーザーにフィードバックを提供する必要があるWPFアプリケーションがあります。デザインは、赤、黄、緑の3つの画像を使用することです。状態に応じて、これらの画像の1つが一度に表示されます。ここにポイントがあります:

  • 3つの画像は、コードビハインドのProperties.Resourcesにあります。
  • 一度に表示される画像は1つだけです。
  • 状態の変化は、コードビハインドのプロセスからのものであり、ユーザーからのものではありません。
  • 画像をコードビハインドから変更できるように、画像コントロールをバインドしたいと思います。

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

WPFプロジェクトの画像リソースはSystem.Drawing.BitmapプロパティをResources.Designer.csに生成しますが、そのリソースから BitmapImage を直接作成できます。イメージファイルの ビルドアクション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);

Image コントロールがXAMLのどこかで次のように宣言されている場合:

<Image x:Name="image"/>

コードビハインドで、画像のSourceプロパティをBitmapImageに設定するだけです。

image.Source = bitmap;

バインドによってSourceプロパティを設定したい場合は、画像URIを返すstringプロパティを作成できます。文字列は、WPFの組み込み BitmapImage によって自動的にTypeConverterに変換されます。

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になります。

32
Clemens