第3回 “見た目”を決めるリソースとスタイル:連載 WPF/Silverlight UIフレームワーク入門(2/3 ページ)
WPF/Silverlightの外観をデザインするには3つの機能を活用すればよい。今回は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>
なお、あくまでアプリケーション起動時の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>
「{x:Static 〜 }」は、静的プロパティをXAMLで使用するためのマークアップ拡張機能。
「SystemColors」はシステムに依存したカラー情報を提供する静的クラスで、そのクラスが持つHighlightBrushKeyプロパティは、文字列や項目の選択時の背景色(ハイライト色)となるブラシのリソース・キーを取得できる静的プロパティだ*1。このほかにも、システムに依存したフォント情報を提供するSystemFontsクラス、画面のサイズやデバイスの有無などといったカラーとフォント以外のさまざまなシステム情報を提供するSystemParametersクラスなどが用意されている。
*1 SystemColorsクラスはSilverlight 2ではサポートされていなかったが、2009年6月現在の最新バージョンであるSilverlight 3 Beta 1では追加されている。
上記のコードを実行してみると、どちらのリソース参照でもハイライト色が取得されることが確認できる。下記の画面はデスクトップ・テーマ「Windows Vista」で上記のコードを実行したものだ。
このアプリケーションを実行したまま、デスクトップ・テーマを「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>
リソース・ディクショナリ・ファイル内のリソースを参照できる範囲は、読み込まれたリソース・ディクショナリに準ずることになる。
複数のリソース・ディクショナリ・ファイルを読み込む場合には、下記のように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>
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>
リソース・ディクショナリをアプリケーションの外部から読み込むことで、「複数のアプリケーションでリソースを共有して外観の統一を図る」といったことや、「リソースを使用してローカリゼーションを行う」といったことができる。
なお、Silverlight 2のResourceDictionaryクラスでは、SourceプロパティもMergedDictionariesプロパティがサポートされておらず、XAMLからリソース・ディクショナリ・ファイルを使用することができなかったが、Silverlight 3 Beta 1では追加されている。
Copyright© Digital Advantage Corp. All Rights Reserved.