web-dev-qa-db-ja.com

WPFスタイルをオーバーライドする代わりに拡張する方法

アプリケーションでカスタムテーマを使用したいのですが、私の知る限り、リソースディクショナリを使用してApp.xamlで参照することでこれを実現できます。スタイルは次のようにデフォルトをオーバーライドします。

<Style TargetType="{x:Type Label">
    <Setter Property="Foreground" Value="Green" />
</Style>

さて、デフォルトのラベルスタイルは同じ値でオーバーライドされますが、すべてのラベルフォントは緑色です。問題は、1つのラベルをどこかにスタイルしたいときに始まります。このようにグリッド内の他のプロパティを変更したいとき

<Grid.Resources>
    <Style TargetType="{x:Type Label">
        <Setter Property="FontSize" Value="28" />
    </Style>
</Grid.Resources>

グリッド内のすべてのラベルの前景色が失われ、デフォルトのラベルが再び設定されています(前の手順でデフォルトを上書きしていませんか?)。何度か試した後、これを正しく行うには、別のプロパティをStyle宣言に追加する必要があることがわかりましたBasedOn={StaticResource {x:Type Label}}"と動作します。アプリ全体で同じBasedOnコードを繰り返す必要があり、これはスタイル設定の仕組みではないため、これは私にとっては奇妙なことです。これは自動的に行われる必要があります。たとえば、HTML + CSSではスタイルが継承およびマージされ、WPFではスタイルが置き換えられます...

スタイルを使用しない場合でも、コントロールはいくつかのシステムテーマ(システムテーマ?)から引き続き表示されることに注意してください。どのようにしてデフォルトを他のどこかで探すように指示して、スタイルに追加のコードがなければ、デフォルトで緑であると思われるようにすることができますか?

BasedOnプロパティの設定を自動化する方法はありますか?それとも、これを全体的に行う方が良いですか?

28
labm0nkey

私も同じ問題を抱えていました。私はザックの答えを使用し、次のように改善したので、スタイルを指定しない場合でも、オーバーライドされたデフォルトが考慮されます。これは基本的にはあなたがやったことですが、ResourceDictionaryで一度だけです。

<Window x:Class="TestWpf.RandomStuffWindow"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
    Title="Random Stuff Window">
  <Window.Resources>
    <ResourceDictionary>
      <!-- Default Label style definition -->
      <Style TargetType="{x:Type Label}">
        <Setter Property="Foreground" Value="Green" />
      </Style>
      <!-- Extending default style -->
      <Style TargetType="{x:Type Label}" 
             x:Key="LargeGreenForegroundLabel" 
             BasedOn="{StaticResource {x:Type Label}}">
        <Setter Property="FontSize" Value="28" />
      </Style>
    </ResourceDictionary>
  </Window.Resources>
  <StackPanel>
    <Button Click="Button_Click">Click</Button>
    <Label Content="GreenForegroundLabel" /> <!-- Uses default style -->
    <Label Style="{StaticResource LargeGreenForegroundLabel}" 
           Content="LargeGreenForegroundLabel" />
  </StackPanel>
</Window>
27
Baptiste

WPFにはさまざまなレベルのスタイルがあり、グローバル>ローカルの順に適用されます。コントロールに直接設定されたスタイルは、例のようにグローバルに設定されたスタイルをオーバーライドします。コントロールがスタイルを探すさまざまな場所すべてのリストを見つけようとしていましたが、現時点では見つけることができません。私の知る限り、スタイルを継承し、ローカルで設定したスタイルでそのスタイルのプロパティを完全に上書きしないようにするには、BasedOnプロパティを使用する必要があります。

次に、別のスタイルに基づくスタイルを持つリソースディクショナリの例を示します。これにより、BasedOnバインディングを何度も繰り返す必要がなくなり、必要な特定の要素にスタイルを設定できますそのスタイルを持っています。

<Window x:Class="TestWpf.RandomStuffWindow"
        xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
        Title="Random Stuff Window">
  <Window.Resources>
    <ResourceDictionary>
      <Style TargetType="{x:Type Label}" 
             x:Key="GreenForegroundLabel">
        <Setter Property="Foreground" Value="Green" />
      </Style>
      <Style TargetType="{x:Type Label}" 
             x:Key="LargeGreenForegroundLabel" 
             BasedOn="{StaticResource GreenForegroundLabel}">
        <Setter Property="FontSize" Value="28" />
      </Style>
    </ResourceDictionary>
  </Window.Resources>
  <StackPanel>
    <Button Click="Button_Click">Click</Button>
    <Label Style="{StaticResource GreenForegroundLabel}" 
           Content="GreenForegroundLabel" />
    <Label Style="{StaticResource LargeGreenForegroundLabel}" 
           Content="LargeGreenForegroundLabel" />
  </StackPanel>
</Window>
10
Zack