WPFのStaticResourceとDynamicResourceの違いは何ですか?
質問
WPFでブラシ、テンプレート、スタイルなどのリソースを使用する場合、StaticResourcesとして指定できます
<Rectangle Fill="{StaticResource MyBrush}" />
またはDynamicResourceとして
<ItemsControl ItemTemplate="{DynamicResource MyItemTemplate}" />
ほとんどの場合(常に?)、1つだけが機能し、他は実行時に例外をスローします。しかし、理由を知りたい:
- 主な違いは何ですか。メモリやパフォーマンスへの影響と同様
- WPFには、「ブラシは常に静的」などのルールがありますか?および「テンプレートは常に動的です」など?
私は想定静的と動的の選択は見た目ほどarbitrary意的ではありません...しかし、パターンを見ることはできません。
解決
A StaticResource は解決されますアプリケーションが実際に実行される前に発生するXAMLの読み込み中にプロパティに割り当てられます。一度だけ割り当てられ、リソースディクショナリへの変更は無視されます。
A DynamicResource が割り当てます読み込み中にプロパティにExpressionオブジェクトを追加しますが、Expressionオブジェクトに値を要求するランタイムまで実際にリソースを検索しません。これにより、実行時に必要になるまでリソースの検索が延期されます。良い例は、後でXAMLで定義されたリソースへの前方参照です。別の例は、実行時まで存在しないリソースです。ソースリソースディクショナリが変更されると、ターゲットを更新します。
他のヒント
私もそれらについて混乱していました。以下の例をご覧ください:
<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がチェックされます。定義していないので、デフォルトが使用されると思います。
以下のコードを追加してButtonのイベントをクリックすると、DynamicResourceが使用されるため、それに応じて背景が更新されます。
private void ButtonNew_Click(object sender, RoutedEventArgs e)
{
this.Resources.Add( "PinkBrush"
,new SolidColorBrush(SystemColors.DesktopColor)
);
}
StaticResourceを使用していた場合:
- リソースはXAMLで宣言する必要があります
- そしてそれも&quot; before&quot ;;それらが使用されます。
いくつかの混乱を解消したいと思います。
StaticResourceはオブジェクトの構築時に解決されます。
DynamicResourceは、コントロールがリソースを必要とするたびに評価および解決されます。
論理リソースを使用すると、XAMLでオブジェクトを定義できます。これはビジュアルツリーの一部ではありませんが、ユーザーインターフェイスで使用できます。論理リソースの例の1つは、カラースキームを提供するために使用されるブラシです。通常、これらのオブジェクトはリソースとして定義され、アプリケーションの複数の要素で使用されます。
<Window.Resources>
<RadialGradientBrush x:Key="myGradientBrush">
<GradientStop Color="Green" Offset="0"/>
<GradientStop Color="Blue" Offset="2"/>
</RadialGradientBrush>
</Window.Resources>
現在、上記で宣言されたリソースは、静的または動的リソースとして使用できます。覚えておくべき1つの点は、静的リソースを使用する場合、参照する前にXAMLコードで最初に定義する必要があることです。静的および動的リソースは次のように使用できます。
<Grid Background="{StaticResource myGradientBrush}"></Grid>
または:
<Grid Background="{DynamicResource myGradientBrush}"></Grid>
StaticResourceとDynamicResourceの違いは、参照要素によるリソースの取得方法にあります。 StaticResourceは、参照要素によって1回だけ取得され、リソースの寿命全体にわたって使用されます。一方、DynamicResourceは、参照されるオブジェクトが使用されるたびに取得されます。
より簡単に言えば、コードでRadialGradientBrushのcolorプロパティがOrangeとPinkに変更されると、リソースがDynamicResourceとして使用される場合にのみ要素に反映されます。以下は、コード内のリソースを変更するコードです。
RadialGradientBrush radialGradientBrush =
new RadialGradientBrush(Colors.Orange, Colors.Pink);
this.Resources["myGradientBrush"] = radialGradientBrush;
DynamicResourceのデメリットは、リソースが使用されるたびに取得されるため、アプリケーションのパフォーマンスが低下することです。ベストプラクティスは、DynamicResourceを使用する特定の理由があるまでStaticResourceを使用することです。
- StaticResourceは first 値を使用します。 DynamicResourceは last の値を使用します。
- DynamicResourceはネストされたスタイリングに使用できますが、StaticResourceは使用できません。
このネストされたスタイルディクショナリがあるとします。ライトグリーンはルートレベルにあり、ピンクはグリッド内にネストされています。
<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は、ボタンをスタイルで見つかった最初の値であるLightGreenとしてレンダリングします。 DynamicResourceは、グリッドをレンダリングするときに、LightGreenボタンをピンクとしてオーバーライドします。
StaticResource
DynamicResource
VS DesignerはDynamicResourceをStaticResourceとして扱うことに注意してください。最初の値を取得します。この場合、VS DesignerはボタンをLightGreenとしてレンダリングしますが、実際にはピンクになります。
StaticResourceは、ルートレベルのスタイル(LightGreen)が削除されるとエラーをスローします。
主な違いは何ですか。メモリやパフォーマンスへの影響と同様
静的リソースと動的リソースの違いは、基礎となるオブジェクトが変更されたときに生じます。 Resourcesコレクションで定義されたBrushがコードでアクセスされ、別のオブジェクトインスタンスに設定されている場合、Rectangleはこの変更を検出しません。
静的リソースは、要素を参照することによって一度取得され、リソースのライフタイムに使用されます。一方、DynamicResourcesは使用されるたびに取得します。
動的リソースの欠点は、アプリケーションのパフォーマンスが低下する傾向があることです。
「ブラシは常に静的です」などのルールがWPFにありますか?および「テンプレートは常に動的です」など?
ベストプラクティスは、コードビハインドのリソースを動的に変更するなどの特定の理由がない限り、静的リソースを使用することです。動的リソースを使用したくないインスタンスの別の例には、SystemBrushes、SystenFonts、およびSystem Parametersを使用する場合が含まれます。
すべての回答が有用であることがわかりました。もう1つのユースケースを追加したいだけです。
複合WPFシナリオでは、ユーザーコントロールは、そのリソースをDynamicResourceとして参照することにより、(このユーザーコントロールをホストする)他の親ウィンドウ/コントロールで定義されたリソースを利用できます。
他の人が述べたように、静的リソースはコンパイル時に検索されます。ユーザーコントロールは、ホスト/親コントロールで定義されているリソースを参照できません。ただし、この場合はDynamicResourceを使用できます。
動的リソースの重要な利点
アプリケーションの起動に非常に長い時間がかかる場合、動的リソースを使用する必要があり、 ウィンドウまたはアプリの作成時に常に静的リソースが読み込まれるのに対し、動的リソースは 初めて使用するときに読み込まれます。
ただし、リソースが非常に大きくない限り、メリットは見られません。 複雑。
動的リソースは、設定されているプロパティが依存オブジェクトから派生したオブジェクト、または静的リソースがどこでも使用できるフリーズ可能オブジェクトにある場合にのみ使用できます。 静的リソースを使用して、コントロール全体を抽象化できます。
静的リソースは次の状況で使用されます:
- 実行時に反応リソースを変更する必要がない場合。
- 多くのリソースで良好なパフォーマンスが必要な場合。
- 同じ辞書内のリソースを参照中。
動的リソース:
- プロパティまたはスタイルセッターテーマの値は、実行時まで不明です
- これには、システム、アプリケーション、テーマベースの設定が含まれます
- これには前方参照も含まれます。
- ページ、ウィンドウ、ユーザーコントロールの読み込み時に読み込まれない可能性のある大きなリソースの参照。
- カスタムコントロールのテーマスタイルの参照。