リソースは、アプリ内のさまざまな場所で再利用できるオブジェクトです。 リソースの例としては、ブラシやスタイルなどがあります。 この概要では、拡張アプリケーション マークアップ言語 (XAML) でリソースを使用する方法について説明します。 コードを使用してリソースを作成してアクセスすることもできます。
注
この記事で説明する XAML リソースは、 通常、コンテンツ、データ、埋め込みファイルなどのアプリに追加されるファイルであるアプリ リソースとは異なります。
XAML でリソースを使用する
次の例では、 SolidColorBrush をページのルート要素のリソースとして定義します。 次に、リソースを参照し、それを使用して、 Ellipse、 TextBlock、 Buttonなど、複数の子要素のプロパティを設定します。
<Window x:Class="resources.ResExample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ResExample" Height="400" Width="300">
<Window.Resources>
<SolidColorBrush x:Key="MyBrush" Color="#05E0E9"/>
<Style TargetType="Border">
<Setter Property="Background" Value="#4E1A3D" />
<Setter Property="BorderThickness" Value="5" />
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush>
<GradientStop Offset="0.0" Color="#4E1A3D"/>
<GradientStop Offset="1.0" Color="Salmon"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="TextBlock" x:Key="TitleText">
<Setter Property="FontSize" Value="18"/>
<Setter Property="Foreground" Value="#4E87D4"/>
<Setter Property="FontFamily" Value="Trebuchet MS"/>
<Setter Property="Margin" Value="0,10,10,10"/>
</Style>
<Style TargetType="TextBlock" x:Key="Label">
<Setter Property="HorizontalAlignment" Value="Right"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="Foreground" Value="{StaticResource MyBrush}"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Margin" Value="0,3,10,0"/>
</Style>
</Window.Resources>
<Border>
<StackPanel>
<TextBlock Style="{StaticResource TitleText}">Title</TextBlock>
<TextBlock Style="{StaticResource Label}">Label</TextBlock>
<TextBlock HorizontalAlignment="Right" FontSize="36" Foreground="{StaticResource MyBrush}" Text="Text" Margin="20" />
<Button HorizontalAlignment="Left" Height="30" Background="{StaticResource MyBrush}" Margin="40">Button</Button>
<Ellipse HorizontalAlignment="Center" Width="100" Height="100" Fill="{StaticResource MyBrush}" Margin="10" />
</StackPanel>
</Border>
</Window>
すべてのフレームワーク レベルの要素 (FrameworkElementまたはFrameworkContentElement) には、定義されたリソースを含むResources型であるResourceDictionary プロパティがあります。 Buttonなど、任意の要素にリソースを定義できます。 ただし、リソースはルート要素で定義されることが最も多く、この例では Window 。
リソース ディクショナリ内の各リソースには、一意のキーが必要です。 マークアップでリソースを定義する場合は、 x:Key ディレクティブを使用して一意のキーを割り当てます。 通常、キーは文字列です。ただし、適切なマークアップ拡張を使用して、他のオブジェクト型に設定することもできます。 リソースの文字列以外のキーは、WPF の特定の機能領域 (特にスタイル、コンポーネント リソース、データ スタイル) で使用されます。
定義されたリソースは、リソースのキー名を指定するリソース マークアップ拡張構文と共に使用できます。 たとえば、リソースを別の要素のプロパティの値として使用します。
<Button Background="{StaticResource MyBrush}"/>
<Ellipse Fill="{StaticResource MyBrush}"/>
前の例では、XAML ローダーが{StaticResource MyBrush}
のBackground プロパティの値Buttonを処理するときに、リソース参照ロジックは最初にリソース ディクショナリでButton
要素をチェックします。
Button
にリソース キー MyBrush
の定義がない場合 (その例では、リソース コレクションは空です)、次にButton
の親要素がチェックされます。 リソースが親で定義されていない場合は、オブジェクトの論理ツリーが見つかるまで上方向にチェックを続けます。
ルート要素にリソースを定義すると、論理ツリー内のすべての要素 ( Window や Pageなど) がアクセスできます。 また、リソースが表すのと同じ型を受け入れるプロパティの値を設定するために、同じリソースを再利用できます。 前の例では、同じ MyBrush
リソースによって 、Button.Background と Ellipse.Fill という 2 つの異なるプロパティが設定 されています。
静的リソースと動的リソース
リソースは、静的または動的として参照できます。 参照は、 StaticResource マークアップ拡張機能 または DynamicResource マークアップ拡張機能を使用して作成されます。 マークアップ拡張は、マークアップ拡張機能で属性文字列を処理し、オブジェクトを XAML ローダーに返すことで、オブジェクト参照を指定できる XAML 機能です。 マークアップ拡張機能の動作の詳細については、「 マークアップ拡張機能と WPF XAML」を参照してください。
マークアップ拡張機能を使用する場合は、通常、その特定のマークアップ拡張によって処理される文字列形式で 1 つ以上のパラメーターを指定します。 StaticResource マークアップ拡張機能は、使用可能なすべてのリソース ディクショナリでそのキーの値を検索することで、キーを処理します。 処理は読み込み中に発生します。これは、読み込みプロセスでプロパティ値を割り当てる必要がある場合です。 代わりに、DynamicResource マークアップ拡張機能は式を作成してキーを処理し、その式はアプリが実行されるまで評価されないままになり、その時点で式が評価されて値が提供されます。
リソースを参照する場合、静的リソース参照と動的リソース参照のどちらを使用するかに、次の考慮事項が影響を与える可能性があります。
アプリのリソースを作成する方法の全体的な設計を決定する場合 (ページごと、アプリ、ルーズ XAML、またはリソースのみのアセンブリで)、次の点を考慮してください。
アプリの機能。 リアルタイムでリソースを更新することは、アプリの要件の一部ですか?
そのリソース参照の種類のそれぞれの参照動作。
特定のプロパティまたはリソースの種類、およびそれらの型のネイティブ動作。
静的リソース
静的リソース参照は、次の状況に最適です。
アプリの設計では、ほとんどのリソースがページ レベルまたはアプリケーション レベルのリソース ディクショナリに集中します。
静的リソース参照は、ページの再読み込みなどのランタイム動作に基づいて再評価されません。 そのため、リソースとアプリの設計に基づいて大量の動的リソース参照が必要ない場合に、大量の動的リソース参照を回避すると、パフォーマンス上の利点がある可能性があります。
DependencyObjectまたはFreezable上にないプロパティの値を設定しています。
アプリ間で共有される DLL にコンパイルされるリソース ディクショナリを作成しています。
カスタム コントロールのテーマを作成し、テーマ内で使用されるリソースを定義しています。
この場合、通常、動的リソース参照参照の動作は必要ありません。 代わりに、静的リソース参照動作を使用して、テーマに対して検索が予測可能で自己完結型になるようにします。 動的リソース参照では、テーマ内の参照であっても、実行時まで評価されないままです。 また、テーマが適用されると、一部のローカル要素によってテーマが参照しようとしているキーが再定義され、ローカル要素が検索のテーマ自体の前に置かれる可能性があります。 その場合、テーマは期待どおりに動作しません。
リソースを使用して、多数の依存関係プロパティを設定しています。 依存関係プロパティには、プロパティ システムによって有効になっている有効な値キャッシュがあるため、読み込み時に評価できる依存関係プロパティの値を指定した場合、依存関係プロパティは再評価された式をチェックする必要がないため、最後の有効な値を返すことができます。 この手法は、パフォーマンス上の利点になる可能性があります。
すべてのコンシューマーの基になるリソースを変更するか、 x:Shared 属性を使用してコンシューマーごとに個別の書き込み可能なインスタンスを保持する必要があります。
静的リソース参照の動作
次に、静的リソースがプロパティまたは要素によって参照されるときに自動的に発生する参照プロセスについて説明します。
検索プロセスでは、プロパティを設定する要素によって定義されたリソース ディクショナリ内で、要求されたキーがチェックされます。
その後、検索プロセスは、親要素とそのリソース ディクショナリに対して論理ツリーを上方向に走査します。 このプロセスは、ルート要素に到達するまで続行されます。
アプリ リソースがチェックされます。 アプリ リソースは、WPF アプリの Application オブジェクトによって定義されるリソース ディクショナリ内のリソースです。
リソース ディクショナリ内からの静的リソース参照は、リソース参照の前に構文的に既に定義されているリソースを参照する必要があります。 前方参照は、静的リソース参照では解決できません。 このため、各リソース ディクショナリの先頭または先頭付近にリソースが定義されるように、リソース ディクショナリ構造を設計します。
静的リソース参照はテーマまたはシステム リソースに拡張できますが、この参照は、XAML ローダーが要求を延期するためだけにサポートされます。 ページの読み込み時のランタイム テーマがアプリに適切に適用されるように、遅延が必要です。 ただし、テーマまたはシステム リソースにのみ存在することがわかっているキーに対する静的リソース参照は推奨されません。これは、テーマがユーザーによってリアルタイムで変更された場合、そのような参照は再評価されないためです。 動的リソース参照は、テーマまたはシステム リソースを要求するときに信頼性が高くなります。 例外は、テーマ要素自体が別のリソースを要求する場合です。 前述の理由から、これらの参照は静的リソース参照にする必要があります。
静的リソース参照が見つからない場合の例外動作は異なります。 リソースが遅延された場合、例外は実行時に発生します。 リソースが遅延されなかった場合、例外は読み込み時に発生します。
動的リソース
動的リソースは、次の場合に最適に機能します。
リソースの値 (システム リソースを含む)、またはユーザーが設定できるリソースは、ランタイムまで不明な条件によって異なります。 たとえば、 SystemColors、 SystemFonts、または SystemParametersによって公開されるシステム プロパティを参照するセッター値を作成できます。 これらの値は、最終的にはユーザーとオペレーティング システムのランタイム環境から取得されるため、本当に動的です。 また、変更可能なアプリケーション レベルのテーマがあり、ページ レベルのリソース アクセスでも変更をキャプチャする必要があります。
カスタム コントロールのテーマ スタイルを作成または参照しています。
アプリの有効期間中に ResourceDictionary の内容を調整する予定です。
相互依存関係を持つ複雑なリソース構造があり、前方参照が必要な場合があります。 静的リソース参照は前方参照をサポートしていませんが、動的リソース参照は、ランタイムまでリソースを評価する必要がないため、それらをサポートします。したがって、前方参照は関連する概念ではありません。
コンパイルまたはワーキング セットの観点から大きなリソースを参照しており、ページが読み込まれるとすぐにリソースが使用されない場合があります。 静的リソース参照は、ページの読み込み時に常に XAML から読み込まれます。 ただし、動的リソース参照は、使用されるまで読み込まれません。
テーマやその他のユーザー設定の影響を受ける他の値からセッター値が取得される可能性があるスタイルを作成しています。
アプリケーションの稼働期間中に論理ツリー内の要素が親を変更する可能性がある場合、それらの要素にリソースを割り当てています。 親を変更すると、リソース参照のスコープも変更される可能性があります。そのため、リソースを再親された要素として新しいスコープに基づいて再評価したい場合は、常に動的リソース参照を使用してください。
動的リソース参照の動作
動的リソース参照のリソース参照動作は、 FindResource または SetResourceReferenceを呼び出すと、コード内の参照動作と並行して行われます。
ルックアップでは、プロパティを設定する要素によって定義されたリソース ディクショナリ内で、要求されたキーがチェックされます。
要素が Style プロパティを定義する場合、要素の System.Windows.FrameworkElement.Style の Resources ディクショナリがチェックされます。
要素が Template プロパティを定義している場合は、要素の System.Windows.FrameworkTemplate.Resources ディクショナリがチェックされます。
ルックアップは、論理ツリーを上方向に走査して親要素とそのリソース ディクショナリに移動します。 このプロセスは、ルート要素に到達するまで続行されます。
アプリ リソースがチェックされます。 アプリ リソースは、WPF アプリの Application オブジェクトによって定義されているリソース ディクショナリ内のリソースです。
現在アクティブなテーマのテーマ リソース ディクショナリがチェックされます。 実行時にテーマが変更されると、値が再評価されます。
システム リソースがチェックされます。
例外の動作 (ある場合) は異なります。
リソースが FindResource 呼び出しによって要求され、見つからなかった場合は、例外がスローされます。
リソースが TryFindResource 呼び出しによって要求され、見つからなかった場合、例外はスローされず、戻り値は
null
。 設定されているプロパティがnull
を受け入れない場合でも、設定されている個々のプロパティに応じて、より深い例外がスローされる可能性があります。リソースが XAML の動的リソース参照によって要求され、見つからなかった場合、動作は一般的なプロパティ システムによって異なります。 一般的な動作は、リソースが存在するレベルでプロパティ設定操作が発生しなかった場合と同じです。 たとえば、評価できなかったリソースを使用して個々のボタン要素に背景を設定しようとすると、値が設定された結果はありませんが、有効な値はプロパティ システムの他の参加者と値の優先順位から取得できます。 たとえば、背景の値は、ローカルで定義されたボタン スタイルまたはテーマ スタイルから取得される場合があります。 テーマ スタイルによって定義されていないプロパティの場合、リソースの評価に失敗した後の有効な値は、プロパティ メタデータの既定値から取得される場合があります。
制約
動的リソース参照には、いくつかの重要な制限があります。 次の条件のうち少なくとも 1 つが当てはまる必要があります。
設定するプロパティは、 FrameworkElement または FrameworkContentElementのプロパティである必要があります。 そのプロパティは、 DependencyPropertyによってサポートされている必要があります。
参照は、
StyleSetter
内の値を対象とします。設定するプロパティは、FreezableまたはFrameworkElementプロパティの値として提供されるFrameworkContentElementのプロパティ、またはSetter値である必要があります。
設定するプロパティは DependencyProperty プロパティまたは Freezable プロパティである必要があるため、プロパティの変更 (変更された動的リソース値) がプロパティ システムによって確認されるため、ほとんどのプロパティ変更が UI に反映される可能性があります。 ほとんどのコントロールには、 DependencyProperty が変更され、そのプロパティがレイアウトに影響する可能性がある場合に、コントロールの別のレイアウトを強制するロジックが含まれます。 ただし、 値として DynamicResource マークアップ拡張機能 を持つすべてのプロパティが、UI でリアルタイムの更新を提供することが保証されているわけではありません。 その機能は、プロパティ、プロパティを所有する型、またはアプリの論理構造によっても異なる場合があります。
スタイル、DataTemplate、および暗黙的なキー
ResourceDictionary内のすべての項目にキーが必要ですが、すべてのリソースが明示的なx:Key
を持つ必要があるわけではありません。 複数のオブジェクト型は、リソースとして定義されている場合に暗黙的なキーをサポートします。この場合、キー値は別のプロパティの値に関連付けられます。 この種類のキーは暗黙的なキーと呼ばれ、 x:Key
属性は明示的なキーです。 明示的なキーを指定することで、暗黙的なキーを上書きできます。
リソースの重要なシナリオの 1 つは、 Styleを定義する場合です。 実際、スタイルは本質的に再利用を目的としているため、 Style はほとんどの場合、リソース ディクショナリのエントリとして定義されます。 スタイルの詳細については、「 スタイルとテンプレート (WPF .NET)」を参照してください。
コントロールのスタイルは、暗黙的なキーを使用して作成することも、参照することもできます。 コントロールの既定の外観を定義するテーマ スタイルは、この暗黙的なキーに依存します。 それを要求する観点からは、暗黙的なキーはコントロール自体の Type です。 リソースを定義する観点からは、暗黙的なキーはスタイルの TargetType です。 そのため、カスタム コントロールのテーマを作成する場合や、既存のテーマ スタイルと対話するスタイルを作成する場合は、そのに Styleを指定する必要はありません。 テーマスタイルを使用する場合は、スタイルを指定する必要はありません。 たとえば、 Style リソースにキーがない場合でも、次のスタイル定義が機能します。
<Style TargetType="Button">
<Setter Property="Background" Value="#4E1A3D" />
<Setter Property="Foreground" Value="White" />
<Setter Property="BorderThickness" Value="5" />
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush>
<GradientStop Offset="0.0" Color="#4E1A3D"/>
<GradientStop Offset="1.0" Color="Salmon"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
そのスタイルには、暗黙的なキー( System.Windows.Controls.Button
型)というキーがあります。 マークアップでは、型名として TargetType を直接指定できます (または、必要に応じて {x:Type...} を使用して Typeを返すことができます。
WPF で使用される既定のテーマ スタイル メカニズムを使用すると、Button自体がそのButton プロパティまたはスタイルへの特定のリソース参照を指定しようとしない場合でも、そのスタイルはページ上のStyleのランタイム スタイルとして適用されます。 ページで定義されているスタイルは、テーマ辞書スタイルが持つのと同じキーを使用し、テーマ辞書スタイルよりも先に検索順序で見つかりました。 ページ内の任意の場所 <Button>Hello</Button>
指定するだけで、 TargetType の Button
で定義したスタイルがそのボタンに適用されます。 必要に応じて、マークアップをわかりやすくするために、 TargetType と同じ型値でスタイルに明示的にキーを設定できますが、これは省略可能です。
OverridesDefaultStyleがtrue
されている場合、スタイルの暗黙的なキーはコントロールには適用されません。 (また、 OverridesDefaultStyle は、コントロールのインスタンスで明示的に設定するのではなく、コントロール クラスのネイティブ動作の一部として設定される場合があることにも注意してください)。また、派生クラスのシナリオで暗黙的なキーをサポートするには、コントロールが DefaultStyleKey をオーバーライドする必要があります (WPF の一部として提供されるすべての既存のコントロールには、このオーバーライドが含まれます)。 スタイル、テーマ、コントロールのデザインの詳細については、「 スタイル可能なコントロールを設計するためのガイドライン」を参照してください。
DataTemplate には暗黙的なキーもあります。 DataTemplateの暗黙的なキーは、DataTypeプロパティ値です。 DataType は、 {x:Type...} を明示的に使用するのではなく、型の名前として指定することもできます。 詳細については、「 データ テンプレートの概要」を参照してください。
こちらも参照ください
.NET Desktop feedback