WPFのStaticResourceとDynamicResourceの違いは何ですか?


474

WPFでブラシ、テンプレート、スタイルなどのリソースを使用する場合、それらはStaticResourcesとして指定できます。

<Rectangle Fill="{StaticResource MyBrush}" />

またはDynamicResourceとして

<ItemsControl ItemTemplate="{DynamicResource MyItemTemplate}"  />

ほとんどの場合(常に?)、一方のみが機能し、もう一方は実行時に例外をスローします。しかし、その理由を知りたいのですが。

  • 主な違いは何ですか。メモリやパフォーマンスへの影響など
  • 「ブラシは常に静的」や「テンプレートは常に動的」などのルールがWPFにありますか?

私は仮定それはそうと、動的対静的間の選択は任意としてではありません...しかし、私は、パターンを見ることができません。


27
Windows 8アプリの開発者は、DyanmicResourceをオプションとして持たず、StaticResourceのみを持っていることに注意することが重要です。
ジェリーニクソン

2
@Jerry Nixonそのおかげで神に感謝します。StaticResourceではなくDynamicResourceを使用していたために何も動作しなかった回数のカウントを失いました。プログラマーの観点からは、これは不必要な複雑さです。類推は変数の定義ですが、ヒープとスタックのどちらに存在するかを明示的に指定する必要がありますか?そして、私がそれを誤解すると、致命的なランタイムエラーがスローされますか?
Contango、2014

StaticResourceとDynamicResourceの詳細、およびそれぞれをいつ使用するかについては、msdn.microsoft.com /en-us/library/ms750613%28v=vs.100%29.aspxを参照してください
マイケルレプッチ

回答:


466

A StaticResourceは解決され、アプリケーションが実際に実行される前に発生したXAMLのロード中にプロパティに割り当てられます。これは1回だけ割り当てられ、リソースディクショナリへの変更は無視されます。

A DynamicResourceは、ロード中にプロパティに表現オブジェクトを割り当てますが、表現オブジェクトが値を求められたときに、実際に実行時までリソースを検索しません。これにより、実行時に必要になるまでリソースの検索が延期されます。良い例は、後でXAMLで定義されるリソースへの前方参照です。もう1つの例は、実行時まで存在しないリソースです。ソースリソースディクショナリが変更されると、ターゲットが更新されます。


4
DynamicResourceを使用する前に何を変更する必要がありますか?たとえば、テンプレートを見てみましょう。テンプレートを1回定義しますが、もちろんトリガーなどでテンプレートのコンテンツを変更できますが、テンプレートは同じです。StaticResourceはここで行いますか?
Isak Savo、

5
アタッチするリソースがXAMLでその使用前に定義されていて、実行中のアプリケーションの存続期間中に変更されない場合は、StaticResourceを使用します。その場合、StaticResourceを使用するとパフォーマンスが向上します。
Phil Wright

4
双方向バインディングはこれらの両方に適用できますか?そうであれば、その場合の違いは何ですか?
WhoIsNinja 2010

11
最後の文は本当に重要です:It will update the target if the source resource dictionary is changed.
MEMark

4
@IsakSavoカラーテーマのUIを検討してください。動的リソースを使用すると、ある辞書を別の辞書と交換でき、新しい辞書でリソースを参照するものはすべて自動的に更新されます。
Gusdor

119

私もそれらについて混乱しました。以下のこの例を参照してください。

<Window x:Class="WpfApplicationWPF.CommandsWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="CommandsWindow" Height="300" Width="300">

    <StackPanel>
        <Button Name="ButtonNew" 
                Click="ButtonNew_Click" 
                Background="{DynamicResource PinkBrush}">NEW</Button>
        <Image Name="ImageNew" 
               Source="pack://application:,,,/images/winter.jpg"></Image>
    </StackPanel>


    <Window.Background>
        <DynamicResource ResourceKey="PinkBrush"></DynamicResource>
    </Window.Background>

</Window>

ここでは、ボタンとウィンドウに動的リソースを使用しており、どこにも宣言していません。実行時に、階層のResourceDictionaryがチェックされます。定義していないため、デフォルトが使用されると思います。

以下のコードをボタンのクリックイベントに追加すると、DynamicResourceを使用するため、それに応じて背景が更新されます。

private void ButtonNew_Click(object sender, RoutedEventArgs e)
{
    this.Resources.Add(  "PinkBrush"
                         ,new SolidColorBrush(SystemColors.DesktopColor)
                       );
}

StaticResourceを使用した場合:

  • リソースはXAMLで宣言する必要があります
  • そして、それらも「前に」使用されます。

混乱を解消したいと思います。


31

StaticResourceはオブジェクトの構築時に解決されます。
DynamicResourceは、コントロールがリソースを必要とするたびに評価および解決されます。


21
  1. StaticResourceは最初の値を使用します。DynamicResourceは最後の値を使用します。
  2. DynamicResourceはネストされたスタイルに使用できますが、StaticResourceは使用できません。

このネストされたスタイルディクショナリがあるとします。LightGreenはルートレベルにあり、Pinkはグリッド内にネストされています。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style TargetType="{x:Type Grid}">
        <Style.Resources>
            <Style TargetType="{x:Type Button}" x:Key="ConflictButton">
                <Setter Property="Background" Value="Pink"/>
            </Style>
        </Style.Resources>
    </Style>
    <Style TargetType="{x:Type Button}" x:Key="ConflictButton">
        <Setter Property="Background" Value="LightGreen"/>
    </Style>
</ResourceDictionary>

ビューで:

<Window x:Class="WpfStyleDemo.ConflictingStyleWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ConflictingStyleWindow" Height="100" Width="100">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Styles/ConflictingStyle.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        <Button Style="{DynamicResource ConflictButton}" Content="Test"/>
    </Grid>
</Window>

StaticResourceはボタンをライトグリーンとしてレンダリングします。これはスタイルで最初に見つかった値です。DynamicResourceは、グリッドをレンダリングするときに、LightGreenボタンをピンクとしてオーバーライドします。

StaticResource StaticResource

DynamicResource DynamicResource

VS DesignerはDynamicResourceをStaticResourceとして扱うことに注意してください。最初の値を取得します。この場合、VS DesignerはボタンをLightGreenとしてレンダリングしますが、実際にはピンクになります。

ルートレベルのスタイル(LightGreen)が削除されると、StaticResourceはエラーをスローします。


13

主な違いは何ですか。メモリやパフォーマンスへの影響など

静的リソースと動的リソースの違いは、基になるオブジェクトが変更されたときに発生します。Resourcesコレクションで定義されたブラシがコードでアクセスされ、別のオブジェクトインスタンスに設定されている場合、Rectangleはこの変更を検出しません。

静的リソースは、参照要素によって一度取得され、リソースの存続期間中使用されます。一方、DynamicResourcesは、使用されるたびに取得します。

動的リソースの欠点は、アプリケーションのパフォーマンスが低下する傾向があることです。

「ブラシは常に静的」や「テンプレートは常に動的」などのルールがWPFにありますか?

コードビハインドでリソースを動的に変更するなどの特別な理由がない限り、ベストプラクティスは静的リソースを使用することです。SystemBrushes、SystenFonts、およびSystem Parametersを使用する場合、動的リソースを使用したいインスタンスの別の例が含まれます。


7

すべての回答が役に立ちました。使用例をもう1つ追加したかっただけです。

複合WPFシナリオでは、ユーザーコントロールは、そのリソースをDynamicResourceとして参照することにより、他の親ウィンドウ/コントロール(このユーザーコントロールをホストする)で定義されたリソースを利用できます。

他の人が述べたように、Staticresourceはコンパイル時に検索されます。ユーザーコントロールは、ホスティング/親コントロールで定義されているリソースを参照できません。ただし、この場合はDynamicResourceを使用できます。


3

動的リソースの重要な利点

アプリケーションの起動に非常に長い時間がかかる場合は、動的リソースを使用する必要があります。静的リソースはウィンドウまたはアプリの作成時に常に読み込まれ、動的リソースは最初に使用されるときに読み込まれるためです。

ただし、リソースが非常に大きく複雑でない限り、メリットはありません。


DynamicResourcesの場合、パフォーマンスの問題は1回だけ作成されますか(初めて使用されます)、または要素が使用されるたびに作成されますか?
モルガン

この場合、ほとんどの使用フィールドは静的リソースでなければならず、カスタム使用フィールドは動的にすることができます。つまり、メインウィンドウリソースは静的で、ダイアログウィンドウリソースは動的にすることができます
zamoldar

2

動的リソースは、設定されているプロパティが依存関係オブジェクトまたはフリーズ可能オブジェクトから派生したオブジェクトにある場合にのみ使用できます。静的リソースはどこでも使用できます。静的リソースを使用して、コントロール全体を抽象化できます。

静的リソースは、次の状況で使用されます。

  1. 実行時に反応リソースを変更する必要がない場合。
  2. たくさんのリソースで良いパフォーマンスが必要な場合。
  3. 同じ辞書内のリソースを参照しているとき。

動的リソース:

  1. プロパティまたはスタイルセッターテーマの値は実行時まで不明です
    • これには、システム、アプリケーション、テーマベースの設定が含まれます
    • これには前方参照も含まれます。
  2. ページ、ウィンドウ、ユーザーコントロールの読み込み時に読み込まれない可能性がある大きなリソースを参照する。
  3. カスタムコントロールでのテーマスタイルの参照。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.