徒然電脳

日々のプログラミング(とその他)忘備録 このサイトは独自研究のみに基づきます マサカリ歓迎しますというかよろしくお願いします

WPFの簡単なまとめ Resorce編

半年以上ぶりです

サボってました。というか、やめてたんですけど復活しときます。
とりあえず忘備録として。
基本的にこれからは以下のサイトを参考にまとめていきます。
Insider.NET > 業務アプリInsider > 連載:WPF入門 - @IT

Resorce?

.NETではリソースのを使うことができます。例えば、外観の設定などを一箇所に定義しておいて、複数のコントロールがそれを実装することができます。じゃあXAMLで書くとどうなるか

MainWindow.xaml

<Window x:Class="Resorce.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <StackPanel.Resources>
            <ResourceDictionary>
                <SolidColorBrush x:Key="Blue" Color="Blue"/>
                <SolidColorBrush x:Key="Red" Color="Red"/>
            </ResourceDictionary>
        </StackPanel.Resources>

        <Button Content="UseResource" Background="{StaticResource Blue}"/>
        <Button Content="UseResource" Background="{StaticResource Red}"/>

    </StackPanel>
</Window>

実行結果
f:id:TempProg:20150704142018j:plain

背景がきちんとリソース通りに動いています。

簡単な使い方

リソースは要素ごとに用意できます。今回の場合はStackPanelにリソース用意したのでStackPanel.Resourcesプロパティで定義。このリソースはStackPanelの子要素すべてが使うことができます。WindowとかGridとかに用意する場合も同様にとかで。

リソースの中にはひとつのResourceDictionaryを持つことができます。
ResourceDictionary内には複数の要素が用意出来ます。今回はSolidColorBrushを二種類。それぞれx:Keyで識別子を設定します。

参照するにはStaticResourceマークアップ拡張で識別子を指定してあげればよいです。

DynamicResourceマークアップ拡張

StaticがあるならDynamicもあるのが通例。今回はデスクトップの背景色を例に違いを見てみます。

MainWindow.xaml

<Window x:Class="Resorce.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <Button Content="UseResource" Background="{StaticResource {x:Static SystemColors.DesktopBrushKey}}"/>
        <Button Content="UseResource" Background="{DynamicResource {x:Static SystemColors.DesktopBrushKey}}"/>
    </StackPanel>
</Window>

Windowsのシステムによる色やフォントのリソースは実は用意されています。ここではデスクトップの背景色を取得するSystemColors.DesktopBrushKeyを利用。これらはx;Staticマークアップ拡張で指定してあげればよいです。実行結果を見てみましょう。

f:id:TempProg:20150704145424j:plain
↑起動時
f:id:TempProg:20150704145426j:plain
↑背景色変更

StaticResourceの方は変更されても変化がない一方、DynamicResourceの方は変化が確認できました。


リソースは大きくなりがち

デザインに凝り始めるとリソースは大きくなることが予想できます。
そこで外部ファイルに定義してあげましょう。

Dictionary.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <!--外部リソース-->
    <SolidColorBrush x:Key="Red" Color="Red" />
    <SolidColorBrush x:Key="Yellow" Color="Yellow"/>
</ResourceDictionary>

MainWindow.xaml

<Window x:Class="Resorce.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <StackPanel.Resources>
            <ResourceDictionary Source="Dictionary.xaml"/>
        </StackPanel.Resources>
        
        <Button Content="UseResource" Background="{StaticResource Red}"/>
        <Button Content="UseResource" Background="{StaticResource Yellow}"/>
    </StackPanel>
</Window>

このようにResourceDictionaryのSorceプロパティにファイル名を指定してあげればいいです。
ただし、外部ファイルの場合IntelliSenseが効かないのが難点でしょうか・・・

なお、ResourceDictionaryはそのMergedDictionariesプロパティで内部に複数のResourceDictionaryを持つことができます。

MainWindow.xaml

<Window x:Class="Resorce.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <StackPanel.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="Dictionary.xaml"/>
                    <ResourceDictionary>
                        <SolidColorBrush x:Key="Blue" Color="Blue"/>
                    </ResourceDictionary>
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </StackPanel.Resources>
        
        <Button Content="UseResource" Background="{StaticResource Red}"/>
        <Button Content="UseResource" Background="{StaticResource Yellow}"/>
        <Button Content="UseResource" Background="{StaticResource Blue}"/>
    </StackPanel>
</Window>

こうすれば外部ディクショナリとMainWinodw.xaml内で定義したリソースの混在が可能です。
もちろんながら外部ディクショナリ同士の結合も可能です。


それでは次回はStyleでお会いしましょう。