WPFのStaticResourceとDynamicResourceの違い

本来投稿しようと思ってトライしていた内容がずっとうまくいかないので脱線・・。

WPFのリソース参照でStaticResourceとDynamicResourceの違いって理解大丈夫ですか?基本かもしれませんが、時折あれっ;と思うことがありますので抑えときましょう。確認用に簡単なアプリを用意してみます。

 MainWindow.xaml

<Window x:Class="WpfResourceDifference.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="329.785">
    <Window.Resources>
        <SolidColorBrush x:Key="testBrush" Color="Red"/>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition Height="30"/>
        </Grid.RowDefinitions>
        <Button Grid.Row="0" Grid.Column="0" Background="{DynamicResource testBrush}"/>
        <Button Grid.Row="1" Grid.Column="0" Background="{StaticResource  testBrush}"/>
        <Grid Grid.Row="2" Grid.Column="0" >
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Button Grid.Row="0" Grid.Column="0" Click="Button_Click_1" >変換①</Button>
            <Button Grid.Row="0" Grid.Column="1" Click="Button_Click_2" >変換②</Button>
            <Button Grid.Row="0" Grid.Column="2" Click="Button_Click_3" >変換③</Button>
        </Grid>
    </Grid>
</Window>

MVVMから外れますがイベントハンドラで処理します、いいんですテストアプリだから。

MainWindow.xaml.cs

namespace WpfResourceDifference
{
    using System.Windows;
    using System.Windows.Media;

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            // 参照オブジェクトのプロパティ変更
            // → StaticResource, DynamicResource両方が影響を受ける
            SolidColorBrush brush = this.FindResource("testBrush") as SolidColorBrush;
            brush.Color = Colors.Blue;
        }

        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            // リソースオブジェクトの差し替え
            // DynamicResourceのみ影響を受ける
            this.Resources["testBrush"] = new SolidColorBrush(Colors.Green);
        }

        private void Button_Click_3(object sender, RoutedEventArgs e)
        {
            // これじゃなにもかわんないよ。
            var resource = this.Resources["testBrush"] as SolidColorBrush;
            resource = new SolidColorBrush(Colors.Green);
        }
    }
}

コメントに動作書きましたが、起動すると真っ赤なふたつのGridが表示されます。

default

変換①ボタン(イベントハンドラ:Button_Click_1)を押すと以下のようになります。

button_1

さらに変換②ボタン(イベントハンドラ:Button_Click_2)を押すと以下のようになります。

button_2

StaticResource

リソースとバインド先の依存関係プロパティの対応付けは起動時の1回のみ、ただしクラスは参照なのでリソースのプロパティの変更はバインド先も影響を受ける。

DynamicResource

リソースとバインド先の依存関係プロパティの対応付けは起動時および起動中(リソースに変更がある度)。つまりリソースのオブジェクトが変わってもバインド先は影響を受けるし、当然リソースのプロパティ変更はバインド先も影響を受ける。

 

あとおまけですが、WPFのリソースにコードでアクセスする場合2通り方法があります。

  // 1
  this.Resources["testBrush"] = new SolidColorBrush(Colors.Green);
  // 2.
  this.FindResource("testBrush") = new SolidColorBrush(Colors.Green);

前者Resourcesインデクサでは該当リソースをthisクラスの中でのみ行うのに対し、後者FindResourceは街頭リソースをthisクラスで探し、存在しなかった場合上層へ探しに行きます。thisクラスがGridであれば、Grid.ResourcesになければMainWindow.Resources、Application.Resourcesも捜索対象にするということです。前者ではGrid.Resourcesしか探しません。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中