WPF イメージリソースを画面表示するために、BitmapをBitmapSourceに変換する

[WPF Tips]

WPF アプリケーション作成で得たTipsをメモ

1.状況

プロジェクトプロパティのリソース(Resource.resx)に画像を登録しておいて、

bitmap_converter02

登録した画像のビルドアクションプロパティをResourceにしておく

bitmap_converter03

と、XAMLで画像を以下のように指定できる。

<Button Command="{Binding OnShowSearchDialog}" CommandParameter="{Binding SelectedSearchCondtion}" Width="26" ToolTip="検索条件を指定しデータを取得します">
    <Image Source="Resources/ic_cloud_download_black_36dp.png" />
</Button>

 

bitmap_converter04

 

ただ、このアイコンを動的に変更使用とすると一手間必要。

bitmap_converter01

上記リソースに登録すると、コード上から、リテラルではなく、Properties.Resource.{リソース名} で参照でき補完も効くし、変更するとコンパイルエラーとなるので非常に便利なので、ViewModelにてプロパティを公開し、バインドしたい。

ちなみに、System.Drawing.Bitmap 型となる。

このViewModelのプロパティをバインドしてもうまくいかない。

using System.Drawing;
private Bitmap _IconImageSource;
public Bitmap IconImageSource
{
    get
    {
        return _IconImageSource;
    }
    set
    {
        _IconImageSource = value;
        RaisePropertyChanged();
    }
}

:

IconImageSource = Properties.Resources.ic_help_outline_black_18dp;

2.対応

BitmapをBitmapSourceに変換するコンバーターを作成し、それを利用する。

3.参考

4.サンプル

4.1 コンバーター

public class WinFormBitmapConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var bitmap = value as Bitmap;

        if (bitmap == null)
        {
            return null;
        }

        try
        {
            using (var memoryStream = new MemoryStream())
            {
                // You need to specify the image format to fill the stream. 
                // I'm assuming it is PNG
                bitmap.Save(memoryStream, ImageFormat.Png);
                memoryStream.Seek(0, SeekOrigin.Begin);


                return CreateBitmapSourceFromBitmap(memoryStream);
            }
        }
        catch (Exception)
        {
            return null;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    private static BitmapSource CreateBitmapSourceFromBitmap(Stream stream)
    {
        var bitmapDecoder = BitmapDecoder.Create(
            stream,
            BitmapCreateOptions.PreservePixelFormat,
            BitmapCacheOption.OnLoad);

        // This will disconnect the stream from the image completely...
        var writable = new WriteableBitmap(bitmapDecoder.Frames.Single());
        writable.Freeze();

        return writable;
    }
}

4.2 Xamlでの利用

<Window x:Class="Shikalog.View.ProgressDialog"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Shikalog.View"
        xmlns:converter="clr-namespace:Shikalog.Common.Converter"
        mc:Ignorable="d">
    <Window.Resources>
        <converter:WinFormBitmapConverter x:Key="BitmapConverter"/>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
        <Image Grid.Row="0" Grid.Column="0" Source="{Binding IconImageSource, Converter={StaticResource BitmapConverter}, Mode=OneWay}" Width="24"/>
        <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Message}" TextWrapping="Wrap" />
    </Grid>
</Window>

以上

Follow me!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です