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」で詳しく説明します。
ここでは、アプリケーション データ ファイルを設定および使用する方法について説明します。
このトピックは、次のセクションで構成されています。
- リソース ファイル
- コンテンツ ファイル
- 起点サイト ファイル
- ビルド タイプ変更後の再ビルド
- 関連トピック
リソース ファイル
特定のアプリケーション データ ファイルを常にアプリケーションで使用できるようにするには、コンパイルしてアプリケーションのメイン実行可能アセンブリまたはその参照アセンブリの 1 つに組み込む必要があります。 この種類のアプリケーション データ ファイルを、リソース ファイルと呼びます。
リソース ファイルは、次のときに使用します。
コンパイルしてアセンブリに組み込んだ後に、リソース ファイルのコンテンツを更新する必要がない。
アプリケーション配布の複雑さを軽減するために、ファイルの依存関係の数を減らす必要がある。
アプリケーション データ ファイルをローカライズ可能にする必要がある (「WPF のグローバリゼーションおよびローカリゼーションの概要」を参照)。
メモ |
---|
リソース ディクショナリ (最上位要素が ResourceDictionary である XAML ファイル) は、WPF リソース ファイルではありません。WPF リソース ファイルをリソース ディクショナリにすることができますが、リソース ディクショナリはリソース ファイルでなくてもかまいません (ResourceDictionary を参照)。 さらに、WPF リソース ファイルは、アセンブリ リソースに対するコア .NET Framework サポートを使用して構成される埋め込みリソースやリンク リソースとは異なります (「アプリケーション リソースの管理」を参照してください)。WPF リソース ファイルは、コア .NET Framework 埋め込みリソース サポートを利用しますが、パッケージの URIs を使用した WPF リソース ファイルへのアクセスは、名前空間を使用する場合よりもはるかに簡単です。 |
リソース ファイルの構成
WPF では、リソース ファイルとは次に示すように Microsoft build engine (MSBuild) プロジェクトに Resource 項目としてインクルードされるファイルです。
<Project "xmlns=https://schemas.microsoft.com/developer/msbuild/2003" ... >
...
<ItemGroup>
<Resource Include="ResourceFile.xaml" />
</ItemGroup>
...
</Project>
メモ |
---|
Microsoft Visual Studio では、リソース ファイルを作成するにはファイルをプロジェクトに追加し、その Build Action を Resource に設定します。 |
プロジェクトをビルドするときに、MSBuild によってリソースがコンパイルされ、アセンブリに組み込まれます。
リソース ファイルの使用
リソース ファイルを読み込むには、Application クラスの GetResourceStream メソッドを呼び出し、目的のリソース ファイルを表すパッケージの URI を渡します。 GetResourceStream からは、StreamResourceInfo オブジェクトが返されます。このオブジェクトによってリソース ファイルが Stream として公開され、そのコンテンツ タイプが記述されます。
次に示すコードの例では、GetResourceStream を使用して Page リソース ファイルを読み込み、Frame (pageFrame) のコンテンツとして設定する方法を示します。
' 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
// 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;
GetResourceStream を呼び出すとStream にアクセスできますが、そのストリームを、設定に使用するプロパティの型に変換する追加作業が必要になります。 代わりに、WPF を使用して、コードでリソース ファイルをある型のプロパティに直接読み込むことによって Stream を開いたり変換したりできます。
次の例は、コードを使用して Page を直接 Frame (pageFrame) に読み込む方法を示しています。
Dim pageUri As New Uri("/PageResourceFile.xaml", UriKind.Relative)
Me.pageFrame.Source = pageUri
Uri pageUri = new Uri("/PageResourceFile.xaml", UriKind.Relative);
this.pageFrame.Source = pageUri;
次の例は、上の例と同じ意味のマークアップです。
<Frame Name="pageFrame" Source="PageResourceFile.xaml" />
リソース ファイルとしてのアプリケーション コード ファイル
ウィンドウ、ページ、フロー ドキュメント、リソース ディクショナリなどのパッケージの URIs を使用して参照できる、特殊な WPF アプリケーション コード ファイルがあります。 たとえば、ウィンドウやページを参照するパッケージの URI を使用して Application.StartupUri プロパティを設定すると、アプリケーションの起動時にそのウィンドウまたはページを読み込むことができます。
<Application
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="SOOPage.xaml" />
これを実行できるのは、次に示すように XAML ファイルが Microsoft build engine (MSBuild) プロジェクトに Page 項目としてインクルードされている場合です。
<Project xmlns="https://schemas.microsoft.com/developer/msbuild/2003" ... >
...
<ItemGroup>
<Page Include="MainWindow.xaml" />
</ItemGroup>
...
</Project>
メモ |
---|
Visual Studio では、新しい Window、NavigationWindow、Page、FlowDocument、または ResourceDictionary をプロジェクトに追加したときの、マークアップ ファイルの Build Action の既定値は Page です。 |
Page 項目を持つプロジェクトがコンパイルされるときに、XAML 項目はバイナリ形式に変換され、コンパイルされて対応するアセンブリに組み込まれます。 したがって、これらのファイルは、通常のリソース ファイルと同様に使用できます。
メモ |
---|
Resource 項目として構成されている XAML ファイルに分離コード ファイルがない場合は、元の XAML をバイナリに変換したものではなく、元の XAML がコンパイルされてアセンブリに組み込まれます。 |
コンテンツ ファイル
コンテンツ ファイルは、実行可能アセンブリと共に圧縮しないファイルとして配布されます。 コンテンツ ファイルはコンパイルされてアセンブリに組み込まれるのではありませんが、アセンブリのコンパイル時に、各コンテンツ ファイルとの関連付けを確立するメタデータが使用されます。
アプリケーションに必要な特定のアプリケーション データ ファイルが更新されても、そのファイルを使用するアセンブリを再コンパイルしなくて済むようにするには、コンテンツ ファイルを使用します。
コンテンツ ファイルの構成
コンテンツ ファイルをプロジェクトに追加するには、アプリケーション データ ファイルを Content 項目としてインクルードする必要があります。 さらに、コンテンツ ファイルはコンパイルされて直接アセンブリに組み込まれるものではないので、ビルド アセンブリからの相対的な場所にコンテンツ ファイルがコピーされることを指定するために MSBuild CopyToOutputDirectory メタデータ要素を設定する必要があります。 プロジェクトがビルドされるたびにビルド出力フォルダーにリソースがコピーされるようにするには、CopyToOutputDirectory メタデータ要素の設定値を Always とします。 それ以外の場合は、リソースの最新バージョンだけがビルド出力フォルダーにコピーされるように、PreserveNewest 値を使用して設定します。
次に示すファイルは、新しいバージョンのリソースがプロジェクトに追加された場合にのみビルド出力フォルダーにコピーされるコンテンツ ファイルとして構成されています。
<Project xmlns="https://schemas.microsoft.com/developer/msbuild/2003" ... >
...
<ItemGroup>
<Content Include="ContentFile.xaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
...
</Project>
メモ |
---|
Visual Studio では、コンテンツ ファイルを作成するにはファイルをプロジェクトに追加し、その Build Action を Content に設定します。また、Copy to Output Directory を Copy 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
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
// 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;
GetContentStream を呼び出すとStream にアクセスできますが、そのストリームを、設定に使用するプロパティの型に変換する追加作業が必要になります。 代わりに、WPF を使用して、コードでリソース ファイルをある型のプロパティに直接読み込むことによって Stream を開いたり変換したりできます。
次の例は、コードを使用して Page を直接 Frame (pageFrame) に読み込む方法を示しています。
Dim pageUri As New Uri("/PageContentFile.xaml", UriKind.Relative)
Me.pageFrame.Source = pageUri
Uri pageUri = new Uri("/PageContentFile.xaml", UriKind.Relative);
this.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 browser application (XBAP) であり、その場所から起動されたアプリケーションに対して許可されるアクセス許可のみをアプリケーションが要求する場合は、アプリケーションの起点サイト (起動場所) からのみ圧縮しないファイルを読み込むことができます。 このようなファイルを、起点サイト ファイルと呼びます。
起点サイト ファイルは部分信頼アプリケーションの唯一のオプションですが、部分信頼アプリケーション以外でも使用できます。 完全信頼アプリケーションでも、読み込むアプリケーション データ ファイルがビルド時点では不明な場合があります。完全信頼アプリケーションでは file:/// を使用できますが、アプリケーション データ ファイルがアプリケーション アセンブリと同じフォルダーにインストールされることも、サブフォルダーにインストールされることも考えられます。 この場合は、起点サイト参照を使用する方が、file:/// を使用するよりも簡単です。file:/// を使用するには、ファイルの完全パスを指定する必要があるからです。
メモ |
---|
起点サイト ファイルは、コンテンツ ファイルとは異なり、クライアント コンピューターの XAML browser application (XBAP) でキャッシュされません。したがって、起点サイト ファイルは明確に要求されたときにのみダウンロードされます。XAML browser application (XBAP) アプリケーションで使用する大容量のメディア ファイルを起点サイト ファイルとして構成すると、アプリケーションの最初の起動時間が大幅に短縮され、ファイルは要求されたときにのみダウンロードされるようになります。 |
起点サイト ファイルの構成
起点サイト ファイルがコンパイル時に存在しない場合や不明な場合は、従来の配置機構 (XCopy コマンド ライン プログラム、Microsoft Windows Installer など) を使用して、必要なファイルが実行時には使用可能になっているようにする必要があります。
起点サイトに配置されるファイルがコンパイル時にわかっているけれども、明示的な依存関係を持たせないようにするには、そのファイルを Microsoft build engine (MSBuild) プロジェクトに None 項目として追加します。 コンテンツ ファイルと同様に、MSBuild の CopyToOutputDirectory 属性を設定して、ビルド アセンブリからの相対位置に起点サイト ファイルがコピーされることを指定する必要があります。値は、Always または PreserveNewest を指定します。
<Project xmlns="https://schemas.microsoft.com/developer/msbuild/2003" ... >
...
<None Include="PageSiteOfOriginFile.xaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
...
</Project>
メモ |
---|
Visual Studio では、起点サイト ファイルを作成するにはファイルをプロジェクトに追加し、その Build Action を None に設定します。 |
プロジェクトをビルドするときに、指定したファイルが MSBuild によってビルド出力フォルダーにコピーされます。
起点サイト ファイルの使用
起点サイト ファイルを読み込むには、Application クラスの GetRemoteStream メソッドを呼び出し、目的の起点サイト ファイルを表すパッケージの URI を渡します。 GetRemoteStream からは、StreamResourceInfo オブジェクトが返されます。このオブジェクトによって起点サイト ファイルが Stream として公開され、そのコンテンツ タイプが記述されます。
次に示すコードの例では、GetRemoteStream を使用して Page 起点サイト ファイルを読み込み、Frame (pageFrame) のコンテンツとして設定する方法を示します。
' 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
// 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;
GetRemoteStream を呼び出すとStream にアクセスできますが、そのストリームを、設定に使用するプロパティの型に変換する追加作業が必要になります。 代わりに、WPF を使用して、コードでリソース ファイルをある型のプロパティに直接読み込むことによって Stream を開いたり変換したりできます。
次の例は、コードを使用して Page を直接 Frame (pageFrame) に読み込む方法を示しています。
Dim pageUri As New Uri("pack://siteoforigin:,,,/Subfolder/SiteOfOriginFile.xaml", UriKind.Absolute)
Me.pageFrame.Source = pageUri
Uri pageUri = new Uri("pack://siteoforigin:,,,/SiteOfOriginFile.xaml", UriKind.Absolute);
this.pageFrame.Source = pageUri;
次の例は、上の例と同じ意味のマークアップです。
<Frame Name="pageFrame" Source="pack://siteoforigin:,,,/SiteOfOriginFile.xaml" />
ビルド タイプ変更後の再ビルド
アプリケーション データ ファイルのビルド タイプを変更した後は、変更を確実に反映するためにアプリケーション全体を再ビルドする必要があります。 アプリケーションのみをビルドしても、変更は適用されません。