私は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" />
あなたと同じ問題を抱えていて、いくらか読んだ後、私は解決策を発見しました - 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
application:
の後の3つのスラッシュは、コンマに置き換える必要があります。
注:パックURIの権限コンポーネントは、パッケージを指す埋め込みURIであり、RFC 2396に準拠している必要があります。さらに、 "/"文字は "、"文字、および "%"などの予約文字に置き換える必要があります。そして「?」エスケープする必要があります。詳細はOPCを見てください。
そしてもちろん、あなたのイメージのbuildアクションをResource
に設定していることを確認してください。
var uriSource = new Uri(@"/WpfApplication1;component/Images/Untitled.png", UriKind.Relative);
foo.Source = new BitmapImage(uriSource);
これにより、 "WpfApplication1"というアセンブリの "Build Action"が "Resource"に設定された "Images"というフォルダに "Untitled.png"という画像がロードされます。
これは少し少ないコードで、一行で実行できます。
string packUri = "pack://application:,,,/AssemblyName;component/Images/icon.png";
_image.Source = new ImageSourceConverter().ConvertFromString(packUri) as ImageSource;
非常に簡単:
メニュー項目の画像を動的に設定するには、次の操作のみを行います。
MyMenuItem.ImageSource =
new BitmapImage(new Uri("Resource/icon.ico",UriKind.Relative));
... "icon.ico"はどこにでも置くことができ(現在は 'Resources'ディレクトリにあります)、Resourceとしてリンクする必要があります...
これを1行に減らすこともできます。これが私のメインウィンドウのアイコンを設定するのに使ったコードです。 .icoファイルがコンテンツとしてマークされていて、出力ディレクトリにコピーされていると仮定します。
this.Icon = new BitmapImage(new Uri("Icon.ico", UriKind.Relative));
最も簡単な方法:
var uriSource = new Uri("image path here");
image1.Source = new BitmapImage(uriSource);
やってみました:
Assembly asm = Assembly.GetExecutingAssembly();
Stream iconStream = asm.GetManifestResourceStream("SomeImage.png");
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = iconStream;
bitmap.EndInit();
_icon.Source = bitmap;
これが私のやり方です:
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"))
これは、イメージパスを動的に設定する例です(イメージはリソースとして構築するのではなく、ディスク上のどこかにあります)。
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では特別な意味を持つため、代わりにエンコードされたバージョン<
を使用する必要があります。これは夢のように機能します!以下は、メニュー項目のアイコンとしてフロッピーディスク記号を示しています。
<MenuItem Name="mnuFileSave" Header="Save" Command="ApplicationCommands.Save">
<MenuItem.Icon>
<Label VerticalAlignment="Center" HorizontalAlignment="Center" FontFamily="Wingdings"><</Label>
</MenuItem.Icon>
</MenuItem>
画像がResourceDictionaryに格納されている場合は、1行のコードでそれを実行できます。
MyImage.Source = MyImage.FindResource("MyImageKeyDictionary") as ImageSource;
もっと簡単な方法もあります。画像がXAMLのリソースとして読み込まれ、問題のコードがそのXAMLコンテンツの分離コードである場合:
Uri iconUri = new Uri("pack://application:,,,/ImageNAme.ico", UriKind.RelativeOrAbsolute);
NotifyIcon.Icon = BitmapFrame.Create(iconUri);
フレームを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" };
もっと簡単な方法もあります。イメージが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"];
リソースアイコンや画像に埋め込まれた画像を読み込む方法(修正版のArcturus):
画像付きのボタンを追加したいとします。あなたは何をするべきか?
今度は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>
完了しました。
私は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;
あなたはちょっと逃しました。
アセンブリから埋め込みリソースを取得するには、ここで説明したように、アセンブリ名とファイル名を一緒に指定する必要があります。
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;
あなたが既にストリームを持っていてフォーマットを知っているなら、あなたはこのようなものを使うことができます:
static ImageSource PngStreamToImageSource (Stream pngStream) {
var decoder = new PngBitmapDecoder(pngStream,
BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
return decoder.Frames[0];
}