WPF アプリケーションのリソース ファイル、コンテンツ ファイル、およびデータ ファイル

Microsoft Windows アプリケーションは多くの場合、Extensible Application Markup Language (XAML)、イメージ、ビデオ、オーディオなど、非実行可能データが含まれるファイルに依存します。 Windows Presentation Foundation (WPF) には、アプリケーション データ ファイルと呼ばれるこれらの種類のデータ ファイルを構成、識別、および使用するための特殊なサポート機能があります。 このサポートの中心となるのは、次のような特定のアプリケーション データ ファイルの種類のセットです。

  • リソース ファイル:実行可能ファイルまたはライブラリ WPF アセンブリにコンパイルされるデータ ファイル。

  • コンテンツ ファイル:実行可能 WPF アセンブリとの明示的な関連付けを持つスタンドアロン データ ファイル。

  • 起点サイト ファイル:実行可能 WPF アセンブリとの関連付けを持たないスタンドアロン データ ファイル。

これらの 3 種類のファイルの重要な違いは、リソース ファイルとコンテンツ ファイルはビルド時に認識されるという点です。アセンブリは、これらを明確に認識します。 ただし、起点サイト ファイルについては、アセンブリはまったく認識しないか、パックの Uniform Resource Identifier (URI) 参照を通じて暗黙的に認識します。後者の場合、参照される起点サイト ファイルが実際に存在することは保証されません。

アプリケーション データ ファイルを参照するために、Windows Presentation Foundation (WPF) はパッケージの Uniform Resource Identifier (URI) スキームを使用します。このスキームについては、「WPF におけるパッケージの URI」で詳しく説明します。

このトピックでは、アプリケーション データ ファイルを構成および使用する方法について説明します。

リソース ファイル (Visual Studio)

アプリケーション データ ファイルを常にアプリケーションで使用可能にするには、コンパイルしてアプリケーションのメイン実行可能アセンブリまたはその参照アセンブリの 1 つに組み込む必要があります。 この種類のアプリケーション データ ファイルを、"リソース ファイル" と呼びます。

リソース ファイルは、次のときに使用します。

  • コンパイルしてアセンブリに組み込んだ後に、リソース ファイルのコンテンツを更新する必要がない。

  • ファイルの依存関係の数を減らして、アプリケーション配布の複雑さを軽減する必要がある。

  • アプリケーション データ ファイルをローカライズ可能にする必要がある (「WPF のグローバリゼーションおよびローカリゼーションの概要」を参照)。

注意

このセクションで説明するリソース ファイルは、「XAML リソース」で説明されているリソース ファイルとも、「アプリケーション リソースの管理 (.NET)」で説明されている埋め込みリソースまたはリンクされたリソースとも異なります。

リソース ファイルの構成

WPF では、リソース ファイルとは Microsoft Build Engine (MSBuild) プロジェクトに Resource 項目としてインクルードされるファイルです。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ... >  
  ...  
  <ItemGroup>  
    <Resource Include="ResourceFile.xaml" />  
  </ItemGroup>  
  ...  
</Project>  

注意

Visual Studio では、リソース ファイルを作成するにはファイルをプロジェクトに追加し、その Build ActionResource に設定します。

プロジェクトをビルドするときに、MSBuild によってリソースがコンパイルされ、アセンブリに組み込まれます。

リソース ファイルの使用

リソース ファイルを読み込むには、Application クラスの GetResourceStream メソッドを呼び出し、目的のリソース ファイルを識別するパック URI を渡します。 GetResourceStream からは、StreamResourceInfo オブジェクトが返されます。このオブジェクトによってリソース ファイルが Stream として公開され、そのコンテンツ タイプが記述されます。

次に示すコードの例では、GetResourceStream を使用して Page リソース ファイルを読み込み、Frame (pageFrame) のコンテンツとして設定する方法を示します。

// Navigate to xaml page
Uri uri = new Uri("/PageResourceFile.xaml", UriKind.Relative);
StreamResourceInfo info = Application.GetResourceStream(uri);
System.Windows.Markup.XamlReader reader = new System.Windows.Markup.XamlReader();
Page page = (Page)reader.LoadAsync(info.Stream);
this.pageFrame.Content = page;
' Navigate to xaml page
Dim uri As New Uri("/PageResourceFile.xaml", UriKind.Relative)
Dim info As StreamResourceInfo = Application.GetResourceStream(uri)
Dim reader As New System.Windows.Markup.XamlReader()
Dim page As Page = CType(reader.LoadAsync(info.Stream), Page)
Me.pageFrame.Content = page

GetResourceStream を呼び出すと Stream にアクセスできますが、設定に使用するプロパティの型にそれを変換する追加作業を実行する必要があります。 代わりに、WPF を使用して、コードでリソース ファイルをある型のプロパティに直接読み込むことによって Stream を開いたり変換したりできます。

次の例は、コードを使用して Page を直接 Frame (pageFrame) に読み込む方法を示しています。

Uri pageUri = new Uri("/PageResourceFile.xaml", UriKind.Relative);
this.pageFrame.Source = pageUri;
Dim pageUri As New Uri("/PageResourceFile.xaml", UriKind.Relative)
Me.pageFrame.Source = pageUri

次の例は、上の例と同じ意味のマークアップです。

<Frame Name="pageFrame" Source="PageResourceFile.xaml" />

リソース ファイルとしてのアプリケーション コード ファイル

ウィンドウ、ページ、フロー ドキュメント、リソース ディクショナリなどのパック URI を使用して、特殊な WPF アプリケーション コード ファイルのセットを参照できます。 たとえば、ウィンドウまたはページを参照するパック URI を使用して Application.StartupUri プロパティを設定すると、アプリケーションの開始時にそのウィンドウまたはページを読み込むことができます。

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    StartupUri="SOOPage.xaml" />

これを実行できるのは、次に示すように XAML ファイルが MSBuild プロジェクトに Page 項目としてインクルードされている場合です。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ... >  
  ...  
  <ItemGroup>  
    <Page Include="MainWindow.xaml" />  
  </ItemGroup>  
  ...  
</Project>  

注意

Visual Studio では、新しい WindowNavigationWindowPageFlowDocument、または ResourceDictionary をプロジェクトに追加したときの、マークアップ ファイルの Build Action の既定値は Page です。

Page 項目を持つプロジェクトがコンパイルされるときに、XAML 項目はバイナリ形式に変換され、コンパイルされて関連するアセンブリに組み込まれます。 したがって、これらのファイルは、通常のリソース ファイルと同様に使用できます。

注意

Resource 項目として構成されている XAML ファイルに分離コード ファイルがない場合は、元の XAML をバイナリに変換したものではなく、元の XAML がコンパイルされてアセンブリに組み込まれます。

コンテンツ ファイル

コンテンツ ファイルは、実行可能アセンブリと共に圧縮しないファイルとして配布されます。 コンテンツ ファイルはコンパイルされてアセンブリに組み込まれるのではありませんが、アセンブリのコンパイル時に、各コンテンツ ファイルとの関連付けを確立するメタデータが使用されます。

アプリケーションに必要な特定のアプリケーション データ ファイルのセットが更新されても、そのファイルを使用するアセンブリを再コンパイルせずに、コンテンツ ファイルを使用する必要があります。

コンテンツ ファイルの構成

コンテンツ ファイルをプロジェクトに追加するには、アプリケーション データ ファイルを Content 項目としてインクルードする必要があります。 さらに、コンテンツ ファイルはコンパイルされて直接アセンブリに組み込まれるものではないため、ビルド アセンブリからの相対的な場所にコンテンツ ファイルがコピーされることを指定するために MSBuild CopyToOutputDirectory メタデータ要素を設定する必要があります。 プロジェクトがビルドされるたびにビルド出力フォルダーにリソースをコピーする場合は、CopyToOutputDirectory メタデータ要素の設定値を Always とします。 それ以外の場合は、リソースの最新バージョンだけがビルド出力フォルダーにコピーされるように、PreserveNewest 値を使用して設定します。

次に示すファイルは、新しいバージョンのリソースがプロジェクトに追加された場合にのみビルド出力フォルダーにコピーされるコンテンツ ファイルとして構成されています。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ... >  
  ...  
  <ItemGroup>  
    <Content Include="ContentFile.xaml">  
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>  
    </Content>  
  </ItemGroup>  
  ...  
</Project>  

注意

Visual Studio では、コンテンツ ファイルを作成するにはファイルをプロジェクトに追加し、その Build ActionContent に設定します。また、Copy to Output DirectoryCopy always (Always と同じ) および Copy if newer (PreserveNewest と同じ) に設定します。

プロジェクトがビルドされるときに、AssemblyAssociatedContentFileAttribute 属性はコンパイルされて各コンテンツ ファイルのアセンブリのメタデータとなります。

[assembly: AssemblyAssociatedContentFile("ContentFile.xaml")]

AssemblyAssociatedContentFileAttribute 値の意味は、プロジェクト内のコンテンツ ファイルの位置を表す相対パスです。 たとえば、コンテンツ ファイルがプロジェクト サブフォルダー内にある場合は、追加のパス情報が AssemblyAssociatedContentFileAttribute 値に組み込まれます。

[assembly: AssemblyAssociatedContentFile("Resources/ContentFile.xaml")]

AssemblyAssociatedContentFileAttribute 値は、ビルド出力フォルダー内のコンテンツ ファイルへのパスの値でもあります。

コンテンツ ファイルの使用

コンテンツ ファイルを読み込むには、Application クラスの GetContentStream メソッドを呼び出し、目的のコンテンツ ファイルを識別するパック URI を渡します。 GetContentStream からは、StreamResourceInfo オブジェクトが返されます。このオブジェクトによってコンテンツ ファイルが Stream として公開され、そのコンテンツ タイプが記述されます。

次に示すコードの例では、GetContentStream を使用して Page コンテンツ ファイルを読み込み、Frame (pageFrame) のコンテンツとして設定する方法を示します。

// Navigate to xaml page
Uri uri = new Uri("/PageContentFile.xaml", UriKind.Relative);
StreamResourceInfo info = Application.GetContentStream(uri);
System.Windows.Markup.XamlReader reader = new System.Windows.Markup.XamlReader();
Page page = (Page)reader.LoadAsync(info.Stream);
this.pageFrame.Content = page;
' Navigate to xaml page
Dim uri As New Uri("/PageContentFile.xaml", UriKind.Relative)
Dim info As StreamResourceInfo = Application.GetContentStream(uri)
Dim reader As New System.Windows.Markup.XamlReader()
Dim page As Page = CType(reader.LoadAsync(info.Stream), Page)
Me.pageFrame.Content = page

GetContentStream を呼び出すと Stream にアクセスできますが、設定に使用するプロパティの型にそれを変換する追加作業を実行する必要があります。 代わりに、WPF を使用して、コードでリソース ファイルをある型のプロパティに直接読み込むことによって Stream を開いたり変換したりできます。

次の例は、コードを使用して Page を直接 Frame (pageFrame) に読み込む方法を示しています。

Uri pageUri = new Uri("/PageContentFile.xaml", UriKind.Relative);
this.pageFrame.Source = pageUri;
Dim pageUri As New Uri("/PageContentFile.xaml", UriKind.Relative)
Me.pageFrame.Source = pageUri

次の例は、上の例と同じ意味のマークアップです。

<Frame Name="pageFrame" Source="PageContentFile.xaml" />

起点サイト ファイル

リソース ファイルは、共に配布されるアセンブリとの間に明示的な関係を持っており、この関係は AssemblyAssociatedContentFileAttribute で定義されます。 ただし、アセンブリとアプリケーション データ ファイル間に暗黙的な関係を持たせる、または関係を持たせない場合があります。たとえば次のような場合です。

  • コンパイル時にファイルが存在しない場合。

  • アセンブリが必要とするファイルが、実行時までわからない場合。

  • 関連付けられているアセンブリを再コンパイルせずにファイルを更新可能にする場合。

  • オーディオやビデオなど大容量のデータ ファイルを使用するアプリケーションで、ユーザーが選択した場合にのみファイルをダウンロードする場合。

このような種類のファイルを、file:/// スキームや http:// スキームなど、従来の URI スキームを使用して読み込むこともできます。

<Image Source="file:///C:/DataFile.bmp" />
<Image Source="http://www.datafilewebsite.com/DataFile.bmp" />

ただし、file:/// スキームや http:// スキームを使用する場合は、アプリケーションに完全信頼が必要です。 アプリケーションが、インターネットまたはイントラネットから起動された XAML ブラウザー アプリケーション (XBAP) であり、その場所から起動されたアプリケーションに対して許可されるアクセス許可のセットのみがアプリケーションによって要求される場合は、アプリケーションの起点サイト (起動場所) からのみ圧縮しないファイルを読み込むことができます。 このようなファイルを、"起点サイト" ファイルと呼びます。

起点サイト ファイルは部分信頼アプリケーションの唯一のオプションですが、部分信頼アプリケーション以外でも使用できます。 完全信頼アプリケーションでも、読み込むアプリケーション データ ファイルがビルド時点では不明な場合があります。完全信頼アプリケーションでは file:/// を使用できますが、アプリケーション データ ファイルがアプリケーション アセンブリと同じフォルダーにインストールされることも、サブフォルダーにインストールされることも考えられます。 この場合は、起点サイト参照を使用する方が、file:/// を使用するよりも簡単です。file:/// を使用するには、ファイルの完全パスを指定する必要があるためです。

注意

起点サイト ファイルは、コンテンツ ファイルとは異なり、クライアント コンピューター上の XAML ブラウザー アプリケーション (XBAP) でキャッシュされません。 したがって、起点サイト ファイルは明確に要求されたときにのみダウンロードされます。 XAML ブラウザー アプリケーション (XBAP) アプリケーションで使用する大容量のメディア ファイルを起点サイト ファイルとして構成すると、アプリケーションの最初の起動時間が大幅に短縮され、ファイルは要求されたときにのみダウンロードされるようになります。

起点サイト ファイルの構成

起点サイト ファイルがコンパイル時に存在しない場合や不明な場合は、従来の配置機構 (XCopy コマンドライン プログラムまたは Microsoft Windows インストーラーなど) を使用して、必要なファイルが実行時には使用可能になっていることを確認する必要があります。

起点サイトに配置されるファイルがコンパイル時にわかっている場合でも、明示的な依存関係を持たせないためには、そのファイルを MSBuild プロジェクトに None 項目として追加します。 コンテンツ ファイルと同様に、MSBuild CopyToOutputDirectory 属性を設定して、ビルド アセンブリからの相対位置に起点サイト ファイルがコピーされることを指定する必要があります。値には、Always または PreserveNewest を指定します。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ... >  
  ...  
  <None Include="PageSiteOfOriginFile.xaml">  
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>  
  </None>  
  ...  
</Project>  

注意

Visual Studio では、起点サイト ファイルを作成するにはファイルをプロジェクトに追加し、その Build ActionNone に設定します。

プロジェクトをビルドするときに、指定したファイルが MSBuild によってビルド出力フォルダーにコピーされます。

起点サイト ファイルの使用

起点サイト ファイルを読み込むには、Application クラスの GetRemoteStream メソッドを呼び出し、目的の起点サイト ファイルを識別するパック URI を渡します。 GetRemoteStream からは、StreamResourceInfo オブジェクトが返されます。このオブジェクトによって起点サイト ファイルが Stream として公開され、そのコンテンツ タイプが記述されます。

次に示すコードの例では、GetRemoteStream を使用して Page 起点サイト ファイルを読み込み、Frame (pageFrame) のコンテンツとして設定する方法を示します。

// Navigate to xaml page
Uri uri = new Uri("/SiteOfOriginFile.xaml", UriKind.Relative);
StreamResourceInfo info = Application.GetRemoteStream(uri);
System.Windows.Markup.XamlReader reader = new System.Windows.Markup.XamlReader();
Page page = (Page)reader.LoadAsync(info.Stream);
this.pageFrame.Content = page;
' Navigate to xaml page
Dim uri As New Uri("/SiteOfOriginFile.xaml", UriKind.Relative)
Dim info As StreamResourceInfo = Application.GetRemoteStream(uri)
Dim reader As New System.Windows.Markup.XamlReader()
Dim page As Page = CType(reader.LoadAsync(info.Stream), Page)
Me.pageFrame.Content = page

GetRemoteStream を呼び出すと Stream にアクセスできますが、設定に使用するプロパティの型にそれを変換する追加作業を実行する必要があります。 代わりに、WPF を使用して、コードでリソース ファイルをある型のプロパティに直接読み込むことによって Stream を開いたり変換したりできます。

次の例は、コードを使用して Page を直接 Frame (pageFrame) に読み込む方法を示しています。

Uri pageUri = new Uri("pack://siteoforigin:,,,/SiteOfOriginFile.xaml", UriKind.Absolute);
this.pageFrame.Source = pageUri;
Dim pageUri As New Uri("pack://siteoforigin:,,,/Subfolder/SiteOfOriginFile.xaml", UriKind.Absolute)
Me.pageFrame.Source = pageUri

次の例は、上の例と同じ意味のマークアップです。

<Frame Name="pageFrame" Source="pack://siteoforigin:,,,/SiteOfOriginFile.xaml" />

ビルドの種類を変更した後のリビルド

アプリケーション データ ファイルのビルドの種類を変更した後は、変更を確実に反映するためにアプリケーション全体をリビルドする必要があります。 アプリケーションのみをビルドしても、変更は適用されません。

関連項目