web-dev-qa-db-ja.com

コードでWPF画像ソースを設定する

私はWPF画像のソースをコードに設定しようとしています。画像はプロジェクトのリソースとして埋め込まれています。例を見ることで、私は以下のコードを思い付きました。どういうわけかそれは働かない - イメージは現われない。

デバッグすると、ストリームに画像データが含まれていることがわかります。だから何が悪いの?

Assembly asm = Assembly.GetExecutingAssembly();
Stream iconStream = asm.GetManifestResourceStream("SomeImage.png");
PngBitmapDecoder iconDecoder = new PngBitmapDecoder(iconStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
ImageSource iconSource = iconDecoder.Frames[0];
_icon.Source = iconSource;

アイコンは次のように定義されています。<Image x:Name="_icon" Width="16" Height="16" />

301
Torbjørn

あなたと同じ問題を抱えていて、いくらか読んだ後、私は解決策を発見しました - Pack URI -

コードで次のことを行いました。

Image finalImage = new Image();
finalImage.Width = 80;
...
BitmapImage logo = new BitmapImage();
logo.BeginInit();
logo.UriSource = new Uri("pack://application:,,,/AssemblyName;component/Resources/logo.png");
logo.EndInit();
...
finalImage.Source = logo;

別のBitmapImageコンストラクタを使用することで、より短くすることができます。

finalImage.Source = new BitmapImage(
    new Uri("pack://application:,,,/AssemblyName;component/Resources/logo.png"));

URIはいくつかの部分に分けられます。

  • 権限:application:///
  • パス:参照アセンブリにコンパイルされているリソースファイルの名前。パスは次の形式に準拠している必要があります。AssemblyShortName[;Version][;PublicKey];component/Path

    • AssemblyShortName:参照されているアセンブリの短縮名.
    • ; Version [optional]:リソースファイルを含む参照されたアセンブリのバージョン。これは、同じ短縮名を持つ2つ以上の参照アセンブリがロードされているときに使用されます。
    • PublicKey [オプション]:参照されるアセンブリに署名するために使用された公開鍵。これは、同じ短縮名を持つ2つ以上の参照アセンブリがロードされているときに使用されます。
    • ; component:参照されているアセンブリがローカルのアセンブリから参照されていることを指定します。
    • / Path:参照先のアセンブリのプロジェクトフォルダのルートに対する相対パスを含むリソースファイルの名前。

application:の後の3つのスラッシュは、コンマに置き換える必要があります。

注:パックURIの権限コンポーネントは、パッケージを指す埋め込みURIであり、RFC 2396に準拠している必要があります。さらに、 "/"文字は "、"文字、および "%"などの予約文字に置き換える必要があります。そして「?」エスケープする必要があります。詳細はOPCを見てください。

そしてもちろん、あなたのイメージのbuildアクションをResourceに設定していることを確認してください。

392
Jared Harley
var uriSource = new Uri(@"/WpfApplication1;component/Images/Untitled.png", UriKind.Relative);
foo.Source = new BitmapImage(uriSource);

これにより、 "WpfApplication1"というアセンブリの "Build Action"が "Resource"に設定された "Images"というフォルダに "Untitled.png"という画像がロードされます。

169
Simon

これは少し少ないコードで、一行で実行できます。

string packUri = "pack://application:,,,/AssemblyName;component/Images/icon.png";
_image.Source = new ImageSourceConverter().ConvertFromString(packUri) as ImageSource;
73
Alex B

非常に簡単:

メニュー項目の画像を動的に設定するには、次の操作のみを行います。

MyMenuItem.ImageSource = 
    new BitmapImage(new Uri("Resource/icon.ico",UriKind.Relative));

... "icon.ico"はどこにでも置くことができ(現在は 'Resources'ディレクトリにあります)、Resourceとしてリンクする必要があります...

41
A Bothe

これを1行に減らすこともできます。これが私のメインウィンドウのアイコンを設定するのに使ったコードです。 .icoファイルがコンテンツとしてマークされていて、出力ディレクトリにコピーされていると仮定します。

 this.Icon = new BitmapImage(new Uri("Icon.ico", UriKind.Relative));
16
Payson Welch

最も簡単な方法:

var uriSource = new Uri("image path here");
image1.Source = new BitmapImage(uriSource);
15
Hasan

やってみました:

Assembly asm = Assembly.GetExecutingAssembly();
Stream iconStream = asm.GetManifestResourceStream("SomeImage.png");
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = iconStream;
bitmap.EndInit();
_icon.Source = bitmap;
14
Andrew Myhre

これが私のやり方です:

internal static class ResourceAccessor
{
    public static Uri Get(string resourcePath)
    {
        var uri = string.Format(
            "pack://application:,,,/{0};component/{1}"
            , Assembly.GetExecutingAssembly().GetName().Name
            , resourcePath
        );

        return new Uri(uri);
    }
}

使用法:

new BitmapImage(ResourceAccessor.Get("Images/1.png"))
11
IlPADlI

これは、イメージパスを動的に設定する例です(イメージはリソースとして構築するのではなく、ディスク上のどこかにあります)。

if (File.Exists(imagePath))
{
    // Create image element to set as icon on the menu element
    Image icon = new Image();
    BitmapImage bmImage = new BitmapImage();
    bmImage.BeginInit();
    bmImage.UriSource = new Uri(imagePath, UriKind.Absolute);
    bmImage.EndInit();
    icon.Source = bmImage;
    icon.MaxWidth = 25;
    item.Icon = icon;
}

アイコンの反射...

最初の考えでは、Iconプロパティには画像しか含めることができないと思います。しかし、実際には何でも含めることができます。私がプログラムでImageプロパティを画像へのパスを持つ文字列に直接設定しようとしたときに、偶然にこれを発見しました。その結果、画像は表示されず、パスの実際のテキストが表示されました。

これにより、アイコン用のイメージを作成する必要がなく、代わりに単純な「アイコン」を表示するために記号フォントを使用したテキストを使用することができます。次の例では、 " - floppydisk"シンボルを含む Wingdingsフォント を使用しています。このシンボルは実際には文字<です。これはXAMLでは特別な意味を持つため、代わりにエンコードされたバージョン&lt;を使用する必要があります。これは夢のように機能します!以下は、メニュー項目のアイコンとしてフロッピーディスク記号を示しています。

<MenuItem Name="mnuFileSave" Header="Save" Command="ApplicationCommands.Save">
  <MenuItem.Icon>
    <Label VerticalAlignment="Center" HorizontalAlignment="Center" FontFamily="Wingdings">&lt;</Label>
  </MenuItem.Icon>
</MenuItem>
8
awe

画像がResourceDictionaryに格納されている場合は、1行のコードでそれを実行できます。

MyImage.Source = MyImage.FindResource("MyImageKeyDictionary") as ImageSource;
6
Hollyroody

もっと簡単な方法もあります。画像がXAMLのリソースとして読み込まれ、問題のコードがそのXAMLコンテンツの分離コードである場合:

Uri iconUri = new Uri("pack://application:,,,/ImageNAme.ico", UriKind.RelativeOrAbsolute);
NotifyIcon.Icon = BitmapFrame.Create(iconUri);
5
Bharat Thanki

フレームをVisualBrushに入れます。

VisualBrush brush = new VisualBrush { TileMode = TileMode.None };

brush.Visual = frame;

brush.AlignmentX = AlignmentX.Center;
brush.AlignmentY = AlignmentY.Center;
brush.Stretch = Stretch.Uniform;

VisualBrushをGeometryDrawingに入れる

GeometryDrawing drawing = new GeometryDrawing();

drawing.Brush = brush;

// Brush this in 1, 1 ratio
RectangleGeometry rect = new RectangleGeometry { Rect = new Rect(0, 0, 1, 1) };
drawing.Geometry = rect;

次にGeometryDrawingをDrawingImageに配置します。

new DrawingImage(drawing);

これを画像のあなたの情報源の上に置いてください。

あなたはそれをはるかに簡単にすることができます:

<Image>
    <Image.Source>
        <BitmapImage UriSource="/yourassembly;component/YourImage.PNG"></BitmapImage>
    </Image.Source>
</Image>

そしてコードで:

BitmapImage image = new BitmapImage { UriSource="/yourassembly;component/YourImage.PNG" };
3
Arcturus

もっと簡単な方法もあります。イメージがXAMLのリソースとしてロードされ、問題のコードがそのXAMLのコードビハインドである場合:

これがXAMLファイルのリソースディクショナリです。気にする必要があるのは、 "PosterBrush"キーを持つImageBrushだけです。残りのコードは、コンテキストを表示するためだけのものです。

<UserControl.Resources>
        <ResourceDictionary>
            <ImageBrush x:Key="PosterBrush" ImageSource="..\Resources\Images\EmptyPoster.jpg" Stretch="UniformToFill"/>

        </ResourceDictionary>
    </UserControl.Resources>

さて、背後にあるコードでは、あなたはただこれを行うことができます

ImageBrush posterBrush = (ImageBrush)Resources["PosterBrush"];
3
Mark Mullin

リソースアイコンや画像に埋め込まれた画像を読み込む方法(修正版のArcturus):

画像付きのボタンを追加したいとします。あなたは何をするべきか?

  1. プロジェクトフォルダアイコンに追加して、ここに画像ClickMe.pngを配置してください
  2. 「ClickMe.png」のプロパティで、「BuildAction」を「Resource」に設定します。
  3. コンパイルしたアセンブリ名が「Company.ProductAssembly.dll」であるとします。
  4. 今度はXAMLで画像を読み込む時が来ました

    <Button Width="200" Height="70">
      <Button.Content>
        <StackPanel>
          <Image Width="20" Height="20">
            <Image.Source>
              <BitmapImage UriSource="/Company.ProductAssembly;component/Icons/ClickMe.png"></BitmapImage>
              </Image.Source>
          </Image>
          <TextBlock HorizontalAlignment="Center">Click me!</TextBlock>
        </StackPanel>
      </Button.Content>
    </Button>
    

完了しました。

2
Siarhei Kuchuk

私はWPFの初心者ですが、.NETの経験はありません。

私は5時間かけて.NET 3.5(Visual Studio 2010)の "WPFカスタムコントロールライブラリプロジェクト"にPNGファイルを追加し、それを画像継承コントロールの背景として設定しようとしました。

URIとの関連はありませんでした。 IntelliSenseを介してリソースファイルからURIを取得する方法がない理由は想像できません。

Properties.Resources.ResourceManager.GetURI("my_image");

私はたくさんのURIを試して、ResourceManager、そしてAssemblyのGetManifestメソッドを使ってみましたが、例外やNULL値がありました。

ここで私は私のために働いたコードをポットします:

// Convert the image in resources to a Stream
Stream ms = new MemoryStream()
Properties.Resources.MyImage.Save(ms, ImageFormat.Png);

// Create a BitmapImage with the stream.
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = ms;
bitmap.EndInit();

// Set as source
Source = bitmap;
2
JoanComasFdz

あなたはちょっと逃しました。

アセンブリから埋め込みリソースを取得するには、ここで説明したように、アセンブリ名とファイル名を一緒に指定する必要があります。

Assembly asm = Assembly.GetExecutingAssembly();
Stream iconStream = asm.GetManifestResourceStream(asm.GetName().Name + "." + "Desert.jpg");
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = iconStream;
bitmap.EndInit();
image1.Source = bitmap;
1
maulik kansara

あなたが既にストリームを持っていてフォーマットを知っているなら、あなたはこのようなものを使うことができます:

static ImageSource PngStreamToImageSource (Stream pngStream) {
    var decoder = new PngBitmapDecoder(pngStream,
        BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
    return decoder.Frames[0];
}
1
user166390