WPF画像リソース


408

私はほとんどがWebで、Windowsフォームの背景を少し持っています。新しいプロジェクトでは、WPFを使用します。WPFアプリケーションでは、説明のために10〜20個の小さなアイコンと画像が必要です。これらを組み込みリソースとしてアセンブリに格納することを考えています。それは正しい方法ですか?

XAMLで、Imageコントロールが埋め込みリソースから画像を読み込むように指定するにはどうすればよいですか?

回答:


473

画像を複数の場所で使用する場合は、画像データをメモリに1回だけロードし、すべてのImage要素間で共有する価値があります。

これを行うには、BitmapSource どこかにリソースとしてを作成します。

<BitmapImage x:Key="MyImageSource" UriSource="../Media/Image.png" />

次に、コードで次のようなものを使用します。

<Image Source="{StaticResource MyImageSource}" />

私の場合、Image.pngファイルをResourceだけではなくのビルドアクションを持つように設定する必要があることがわかりましたContent。これにより、コンパイルされたアセンブリ内でイメージが実行されます。


6
これを動的に行うことは可能でしょうか?起動時にロードするイメージの数が異なる場合、イメージごとにBitmapSourceを作成し、上記と同じ方法で参照できますか?
ベッキーフランクリン

2
@Becky-はい、できます。ただし、Xamlで参照する場合は、コンパイル時にキーを知っていると想定して、DynamicResourceではなくマークアップ拡張を使用する必要がある場合がありStaticResourceます。WPFでは、実行時にリソースディクショナリを作成できます。実際、これはXamlドキュメントをロードしたときに発生することであり、同等のC#が表示されないだけです。
Drew Noakes、2010

9
私が当てたもの:画像リソースをリソースディクショナリに追加する場合は、コンポーネントのXAMLでその画像ディクショナリを参照することを忘れないでください。例:<UserControl.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source = "Dictionary1.xaml" /> </ResourceDictionary.MergedDictionaries> </ ResourceDictionary> </UserControl.Resources>
Dan Mitchell

4
通常はに追加Width="{Binding Source.PixelWidth, RelativeSource={RelativeSource Self}}" Imageます。そうしないと、何らかの理由で画像がグロテスクに拡大されることがよくあります(たとえば、16x16のアイコンが200x200ピクセルのように引き伸ばされているなど)。
またはMapper

5
参照されたアセンブリのresourcedictionaryでBitmapImageが宣言されている場合、これが機能するにはUriSourceがpackURIである必要があることがわかりました。それ以外の場合は、VSのxamlエディターで画像を表示できますが、デバッグ時には画像を表示できません。パックURI:msdn.microsoft.com/en-au/library/aa970069
v

174

画像、動画などを使用するベストプラクティスであることがわかりました。

  • ファイルを「ビルドアクション」「コンテンツ」に変更します。[ ビルドディレクトリにコピー]をオンにしてください。
    • ソリューションエクスプローラーウィンドウの[右クリック]メニューにあります。
  • 次の形式の画像ソース
    • "/ «YourAssemblyName» ; component /«YourPath»/«YourImage.png» "

<Image Source="/WPFApplication;component/Images/Start.png" />

利点:

  • ファイルはアセンブリに埋め込まれません。
    • リソースマネージャーは、(ビルド時に)リソースが多すぎると、いくつかのメモリオーバーフローの問題を引き起こします。
  • アセンブリ間で呼び出すことができます。

36
リソースをアセンブリに埋め込む場合も、この同じアプローチが機能しますが、「ビルドアクション」を「リソース」に設定する必要があります。
アシュレイデイビス

5
うまくいきました。その他の注意事項:「コンポーネント」は「現状のまま」必要であり、「画像」はプロジェクト内のpngの相対パスです。つまり、ルートに配置される画像は "<Image Source =" / WPFApplication; component / Start.png "/>"になります
Badiboy

3
C#でこれを行う方法の例がいいでしょう。(これは有効なURIではないため、BitmapImageの構築時に使用することはできません。)
Vaccano

5
では、ファイルが埋め込みリソースに設定されている場合はどうすればよいでしょうか?これは機能していないようです。また、プロジェクトにイメージを2回含めたくありません。(すでに埋め込みリソースとして使用しています。)
BrainSlugs83

2
「コンポーネント」がパスのどこにどのようにして入りますか。それは一部の仕様の一部ですか?
Triynko、2014

46

一部の人々は、コードでこれを行うことについて質問し、答えを得ません。

検索に何時間も費やした後、私は非常に簡単な方法を見つけました、私は例を見つけられなかったので、私はここで画像で機能する私のものを共有します。(私は.gifでした)

概要:

これは、ImageSourceの「宛先」が好むと思われるBitmapFrameを返します。

使用する:

doGetImageSourceFromResource ("[YourAssemblyNameHere]", "[YourResourceNameHere]");

方法:

static internal ImageSource doGetImageSourceFromResource(string psAssemblyName, string psResourceName)
{
    Uri oUri = new Uri("pack://application:,,,/" +psAssemblyName +";component/" +psResourceName, UriKind.RelativeOrAbsolute);
    return BitmapFrame.Create(oUri);
}

学習:

私の経験から、パック文字列は問題ではありません。ストリームを確認してください。特に、初めて読み込むときにポインターがファイルの最後に設定されている場合は、再度読み込む前にゼロに再設定する必要があります。

これにより、この作品の多くの時間を節約できることを願っています。


44

私の画像Freq.pngがフォルダーにIconsあり、次のように定義されている実行中のアセンブリにリソースをロードするコードResource

this.Icon = new BitmapImage(new Uri(@"pack://application:,,,/" 
    + Assembly.GetExecutingAssembly().GetName().Name 
    + ";component/" 
    + "Icons/Freq.png", UriKind.Absolute)); 

私も関数を作りました:

/// <summary>
/// Load a resource WPF-BitmapImage (png, bmp, ...) from embedded resource defined as 'Resource' not as 'Embedded resource'.
/// </summary>
/// <param name="pathInApplication">Path without starting slash</param>
/// <param name="assembly">Usually 'Assembly.GetExecutingAssembly()'. If not mentionned, I will use the calling assembly</param>
/// <returns></returns>
public static BitmapImage LoadBitmapFromResource(string pathInApplication, Assembly assembly = null)
{
    if (assembly == null)
    {
        assembly = Assembly.GetCallingAssembly();
    }

    if (pathInApplication[0] == '/')
    {
        pathInApplication = pathInApplication.Substring(1);
    }
    return new BitmapImage(new Uri(@"pack://application:,,,/" + assembly.GetName().Name + ";component/" + pathInApplication, UriKind.Absolute)); 
}

使用法(関数をResourceHelperクラスに配置することを想定):

this.Icon = ResourceHelper.LoadBitmapFromResource("Icons/Freq.png");

WPFのMSDN Pack URIを参照してください:
pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml


新しいUriが無効なURIをスロー:無効なポートが指定されました。
Steve

問題のURIはありますか?
Eric Ouellet

1
自分のURIと同じですが、WinformがホストするWPF内で実行されていました。また、新しいUriを呼び出したとき、「pack」スキーマはまだ登録されていませんでした。
Steve

1
おっと... winformでホストされているWPFにリテイトされている可能性があります。申し訳ありません。あまり一般的な使い方ではないと思いますので修正はしません。幸運を!
Eric Ouellet、2016

私の場合、使用することnew Uri(@"pack://application:,,,/" + pathInApplication)もトリックをしました。
Adam Calvet Bohl

40

はい、それは正しい方法です。

パスを使用するだけで、リソースファイル内の画像を使用できます。

<Image Source="..\Media\Image.png" />

イメージファイルのビルドアクションを「リソース」に設定する必要があります。


1
これをありがとう。ImageSourceを使用して同様のことを行う方法はありますか?本質的に画像をリソースディクショナリに一度ロードします。このアプローチでは、画像データがメモリに複数回読み込まれることを恐れています。
Drew Noakes

2
これは、コードをリファクタリングする必要があるときに混乱します。xamlドキュメントで名前空間が変更された場合は、すべての画像参照を手動で変更する必要があります。Drew Noakesによって記述された方法は、はるかにスムーズで保守可能です。
Kasper Holdum、2009年

14

リソースの使用方法の詳細:WPFアプリケーションリソース、コンテンツ、およびデータファイル

また、それらを参照する方法については、「URIをWPFにパックする」を参照してください。

つまり、参照された/参照しているアセンブリからリソースを参照する手段さえあります。


リンクは生きているようです(ただし、「このドキュメントはアーカイブされてお​​り、メンテナンスされていません。」と表示されています)。
Peter Mortensen、

5
  1. Visual Studio 2010 Professional SP1。
  2. .NET Framework 4クライアントプロファイル。
  3. プロジェクトのプロパティのリソースとして追加されたPNG画像。
  4. Resourcesフォルダーに新しいファイルが自動的に作成されます。
  5. ビルドアクションがリソースに設定されました。

これは私のために働きました:

<BitmapImage x:Key="MyImageSource" UriSource="Resources/Image.png" />

3

Blendを使用している場合、それをさらに簡単にし、Source属性の正しいパスを取得するのに問題がないようにするには、プロジェクトパネルからデザイナーに画像をドラッグアンドドロップするだけです。


3

はい、それは正しい方法です。次のパスを使用して、リソースファイルで画像を使用できます。

<StackPanel Orientation="Horizontal">
    <CheckBox  Content="{Binding Nname}" IsChecked="{Binding IsChecked}"/>
    <Image Source="E:\SWorking\SharePointSecurityApps\SharePointSecurityApps\SharePointSecurityApps.WPF\Images\sitepermission.png"/>
    <TextBlock Text="{Binding Path=Title}"></TextBlock>
</StackPanel>

-5

以下は機能し、設定される画像はプロパティのリソースです:

    var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(MyProject.Properties.Resources.myImage.GetHbitmap(),
                                      IntPtr.Zero,
                                      Int32Rect.Empty,
                                      BitmapSizeOptions.FromEmptyOptions());
    MyButton.Background = new ImageBrush(bitmapSource);
img_username.Source = bitmapSource;

5
違反はありませんが、これは悪い習慣のようなにおいがします。
ShloEmi 2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.