連載
» 2009年06月16日 00時00分 公開

連載 WPF/Silverlight UIフレームワーク入門:第3回 “見た目”を決めるリソースとスタイル (2/3)

[八巻雄哉,グレープシティ株式会社]

動的リソース参照

 動的リソース参照では、アプリケーションの起動時にリソース・キーの検索が行われず、代わりに、後でリソース・キーの検索を行う際に使用する一時的な式が作成される。そして、リソース・キーの検索は、アプリケーションの実行後、リソースが必要になった際に都度行われる。

 指定されたリソース・キーが参照可能な範囲内に存在しない場合、例外は発生せず、参照元のプロパティには何も値が設定されなった状態(デフォルト値)となる。リソース・キー検索の順序は、基本的には静的リソース参照と同様である。

 想定される動的リソース参照が必要なケースは、主に下記の2つである。

  • アプリケーション起動時のXAMLコードの処理順序に依存することなくリソース参照を行いたい場合

 動的リソース参照のリソース・キー検索はアプリケーションの実行時に都度行われるため、アプリケーション起動時のXAMLコードの処理順序に依存しない。

 先ほどの静的リソースにおけるサンプルの場合、下記のようにDynamicResourceマークアップ拡張機能による動的リソース参照を用いることで、<Ellipse>要素のResourcesプロパティに宣言された青色のMyBrushを適用することができる。

<Grid>
  <Grid.Resources>
    <SolidColorBrush x:Key="MyBrush" Color="Red"/>
  </Grid.Resources>

  <!-- 動的リソース参照 -->
  <Ellipse Fill="{DynamicResource MyBrush}">
    <Ellipse.Resources>
      <SolidColorBrush x:Key="MyBrush" Color="Blue"/>
    </Ellipse.Resources>
  </Ellipse>
</Grid>

動的リソース参照を使用して青色のMyBrushを参照するコード例(XAML)

 なお、あくまでアプリケーション起動時のXAMLコードの処理順序に依存しなくなるというだけで、リソース・キーの検索範囲は静的リソースと変わらない。リソースをどこに配置しても参照できるようになるわけではないので、注意していただきたい。

  • リソースの値が、システムやほかのアプリケーションといったアプリケーションの外部から決定、変更される場合

 WindowsアプリケーションであるWPFでは、デスクトップ・テーマが変更されたときに、それに合わせて画面やコントロールの外観を変更するといった動作が必要になることがある。

 アプリケーションの実行中にデスクトップ・テーマが変更された場合、アプリケーション起動時にのみリソース・キーの検索が行われる静的リソース参照では、デスクトップ・テーマに依存したリソース参照が再評価されない。リソースが必要になった際に都度リソース・キーの検索が行われる動的リソース参照を使用することで、このようなケースに対応することができる。

 下記のコード例では、静的リソース参照と動的リソース参照のそれぞれを使用して、同じシステム依存のリソースを参照している。

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition/>
    <RowDefinition/>
  </Grid.RowDefinitions>

  <Ellipse
    Fill="{StaticResource {x:Static SystemColors.HighlightBrushKey}}" />

  <Ellipse Grid.Row="1"
    Fill="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />

</Grid>

静的リソース参照と動的リソース参照の2つを使用してシステム依存のリソースを参照するコード例(XAML)
「{x:Static 〜 }」は、静的プロパティをXAMLで使用するためのマークアップ拡張機能。

 「SystemColors」はシステムに依存したカラー情報を提供する静的クラスで、そのクラスが持つHighlightBrushKeyプロパティは、文字列や項目の選択時の背景色(ハイライト色)となるブラシのリソース・キーを取得できる静的プロパティだ*1。このほかにも、システムに依存したフォント情報を提供するSystemFontsクラス、画面のサイズやデバイスの有無などといったカラーとフォント以外のさまざまなシステム情報を提供するSystemParametersクラスなどが用意されている。

*1 SystemColorsクラスはSilverlight 2ではサポートされていなかったが、2009年6月現在の最新バージョンであるSilverlight 3 Beta 1では追加されている。


 上記のコードを実行してみると、どちらのリソース参照でもハイライト色が取得されることが確認できる。下記の画面はデスクトップ・テーマ「Windows Vista」で上記のコードを実行したものだ。

デスクトップ・テーマ「Windows Vista」
静的リソース参照と動的リソース参照の2つを使用して、システムのハイライト色で描画している。

 このアプリケーションを実行したまま、デスクトップ・テーマを「Windowsクラシック」に変更すると下記のような画面となる。

デスクトップ・テーマ「Windowsクラシック」
下方の動的リソース参照を使用した描画が、「Windowsクラシック」テーマのハイライト色に変化している。

 静的リソース参照を使用したEllipseは色が変化していないのに対して、動的リソース参照を使用したEllipseでは「Windowsクラシック」のハイライト色が適用されていることを確認できる。

 このほかにも動的リソース参照によって解決できるケースは存在するが、極めて特殊なケースであるため、本稿での紹介は割愛する。

リソース・ディクショナリ・ファイル

 リソース・ディクショナリは、別個のXAMLファイル(リソース・ディクショナリ・ファイル)として作成することもできる。次のコードはそのファイル内容の例だ。

<ResourceDictionary
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <SolidColorBrush x:Key="BlueBrush" Color="Blue"/>
</ResourceDictionary>

最も単純なリソース・ディクショナリ・ファイルのコード例
拡張子は「.XAML」となる。

 リソース・ディクショナリ・ファイルの最も単純な利用方法は、プロジェクトに追加し、それをイミディエイト・リソース、もしくはアプリケーション・リソースに読み込むことだ。そのためには、ResourceDictionaryクラスが持つSourceプロパティを使用する。

 上記のリソース・ディクショナリ・ファイルが「ResourceDictionary1.xaml」というファイル名だった場合、下記のようなコードで、これを<Grid>要素のリソース・ディクショナリに読み込むことができる。

<Grid>
  <Grid.Resources>
    <ResourceDictionary Source="ResourceDictionary1.xaml"/>
  </Grid.Resources>

  <Ellipse Fill="{StaticResource BlueBrush}" />

</Grid>

ResourceDictionaryクラスが持つSourceプロパティを使用してリソース・ディクショナリ・ファイルを読み込むコード例(XAML)

 リソース・ディクショナリ・ファイル内のリソースを参照できる範囲は、読み込まれたリソース・ディクショナリに準ずることになる。

 複数のリソース・ディクショナリ・ファイルを読み込む場合には、下記のようにMergedDictionariesプロパティを使用して、リソース・ディクショナリをマージする方法を取る。

<Grid>
  <Grid.Resources>
    <ResourceDictionary>
      <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="ResourceDictionary1.xaml"/>
        <ResourceDictionary Source="ResourceDictionary2.xaml"/>
      </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
  </Grid.Resources>

  <Ellipse e Fill="{StaticResource BlueBrush}" />

</Grid>

MergedDictionariesプロパティを使用して2つのリソース・ディクショナリ・ファイルを読み込むコード例(XAML)

 SourceプロパティはUri型となっており、さまざまな場所からのファイルの読み込みがサポートされている。とてもこの場では紹介しきれないため、詳細についてはMSDNライブラリの「Uri クラス (System)」や「Windows Presentation Foundation におけるパッケージの URI」をご参照いただきたい。

 ここでは、アプリケーションの外部からリソース・ディクショナリ・ファイルを読み込む一例として、参照先の外部アセンブリにリソースとして埋め込まれている場合を紹介する。

 アプリケーションの参照アセンブリとして「ClassLibrary1」が存在し、そのアセンブリのリソースとしてResourceDictionary1.xamlが埋め込まれている場合、下記のようなコードでResourceDictionary1.xamlを読み込むことができる。

<Grid>
  <Grid.Resources>
    <ResourceDictionary
      Source="pack://application:,,,/ClassLibrary1;component/ResourceDictionary1.xaml" />
  </Grid.Resources>

  <Ellipse e Fill="{StaticResource BlueBrush}" />

</Grid>

参照アセンブリに埋め込まれたリソースからリソース・ディクショナリ・ファイルを読み込むコード例(XAML)

 リソース・ディクショナリをアプリケーションの外部から読み込むことで、「複数のアプリケーションでリソースを共有して外観の統一を図る」といったことや、「リソースを使用してローカリゼーションを行う」といったことができる。

 なお、Silverlight 2のResourceDictionaryクラスでは、SourceプロパティもMergedDictionariesプロパティがサポートされておらず、XAMLからリソース・ディクショナリ・ファイルを使用することができなかったが、Silverlight 3 Beta 1では追加されている。

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。