◆ デフォルトのスタイルは Application.Resources にまとめる
◆ ResourceDictionary に書いておいてまとめることができる 

WPF のリソースは FrameworkElement のプロパティと Application のプロパティに設定できます

こういう感じ
<Window 略>
    <Window.Resources>
        <Style TargetType="Button">
            <Setter Property="Background" Value="#efe0fe" />
        </Style>

        <s:Boolean x:Key="true">True</s:Boolean>
        <local:TestConverter x:Key="test_converter"/>
    </Window.Resources>
</Window>

リソースには好きなオブジェクトを置いておけます
よく使う色やアイコン画像や Converter などいろいろです

基本的に XAML のプロパティ設定のときに StaticResource で指定するのが使いみちです
<Label Content="{Binding path,Converter={StaticResource test_converter},ConverterParameter={StaticResource true}}"/>

Style

Resources 内の Style で TargetType で指定した種類のコントロールのスタイルを設定できます
x:Key は省略できて 省略すればそのリソースを持つコントロールの子孫要素全てに対して TargetType で設定したスタイルが適用されます

上のコードは Window がもっているリソースに Button の背景色が #efe0fe とあるので この Window の中にあるすべての Button は #efe0fe 色が背景になります

優先順はその要素から徐々に上の階層をみていきます
<Window>
    <Grid>
        <StackPanel>
            <CheckBox>
                <TextBlock>
                    あ
                </TextBlock>
            </CheckBox>
        </StackPanel>
    </Grid>
</Window>

こういうのだと TextBlock のリソースが最優先で 次に CheckBox → StackPanel → Grid → Window の順になります

Window.Resources に Style を設定しておけば その Window の中の全体が対象ですが ひとつの Window だけじゃなくてアプリケーション全体を対象にしたいときは App.xaml にある Applcation.Resources に設定します

ネスト

あちこちに Resources 書くと見づらくなるので Window.Resources に Button など他の要素のスタイルも書くことができます

Window.Resources に TargetType が Button の Style をつくれば その Window の中の Button に対するスタイルです
その Style にも Style.Resources を指定することができます
Style.Resources に TargetType が Label の Style を作れば Window のなかの Button のなかの Label が対象です

CSS でいう
window button label {}
みたいな感じです

サンプル

<Window.Resources>
    <Style TargetType="Button">
        <Setter Property="Foreground" Value="Purple"/>
        <Style.Resources>
            <Style TargetType="Label">
                <Setter Property="Foreground" Value="Red"/>
            </Style>
            <Style TargetType="TextBlock">
                <Setter Property="Foreground" Value="Blue"/>
            </Style>
        </Style.Resources>
    </Style>
</Window.Resources>
<StackPanel>
    <Button>
        <Label>abc</Label>
    </Button>
    <Button>
        <TextBlock>abc</TextBlock>
    </Button>
    <Button>abc</Button>
</StackPanel>

temp


1 つめは Label の中なので赤色
2 つめは TextBlock の中なので青色
3 つめは Button のスタイルで紫色です

Button の VisualTree を見ると 文字の表示には TextBlock が使われているので 2 つめと 3 つめは同じツリー構造です
なのに 3 つめには TextBlock のスタイルが適用されていません
実際に XAML に書いた LogicalTree でスタイルが当たってるようです

デフォルトスタイル

Resources は便利ですけど 1 つの Resources に同じ TargetType の Style を複数書けません

Button を継承して拡張した Buttton クラスを作ったとします
その XAML でデフォルトのスタイルをこのように指定します
<Button x:Class="liblib.wpf.Buttton"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:liblib.wpf"
        mc:Ignorable="d"
        d:DesignHeight="300" d:DesignWidth="300">
    <Button.Resources>
        <Style TargetType="local:Buttton">
            <Setter Property="Background" Value="Orange"/>
        </Style>
    </Button.Resources>
</Button>

このコントロールを使う Window でリソースを設定すると実行時にエラーが起きます
<local:Buttton>
    <local:Buttton.Resources>
        <Style TargetType="local:Buttton">
            <Setter Property="Foreground" Value="Blue" />
        </Style>
    </local:Buttton.Resources>
    abc
</local:Buttton>

local:Buttton.Resources の Style は Buttton.xaml のほうにあるのでここで設定すると 2 つあることになってしまいます


直接 local:Buttton の Resources でなく Window に設定すれば 2 つあることは回避できます
<Window.Resources>
    <Style TargetType="local:Buttton">
        <Setter Property="Background" Value="Aqua"/>
        <Setter Property="Foreground" Value="Blue"/>
    </Style>
</Window.Resources>
<local:Buttton>
    abc
</local:Buttton>

ですが こうしても local:Buttton につけられている Resources のほうが優先されるので 背景が Orange になるだけで Window.Resources で設定した Style は無視されてしまいます


local:Buttton.Resources でなく local:Buttton.Style を設定することもできます
<local:Buttton>
    <local:Buttton.Style>
        <Style TargetType="local:Buttton">
            <Setter Property="Foreground" Value="Blue"/>
        </Style>
    </local:Buttton.Style>
    abc
</local:Buttton>

Resources より Style が優先なので このコードでは 文字色が青色になりますが背景は Orange にならずデフォルトのボタン色です

背景を引き継ぎたいなら BasedOn を Style に設定します
<local:Buttton>
    <local:Buttton.Style>
        <Style TargetType="local:Buttton" BasedOn="{StaticResource {x:Type local:Buttton}}">
            <Setter Property="Foreground" Value="Blue"/>
        </Style>
    </local:Buttton.Style>
    abc
</local:Buttton>

これだと Style だけの設定なので Resources にあれこれ含めたい場合は .Resources もかかないといけません
<local:Buttton>
    <local:Buttton.Style>
        <Style TargetType="local:Buttton" BasedOn="{StaticResource {x:Type local:Buttton}}">
            <Setter Property="Foreground" Value="Blue"/>
        </Style>
    </local:Buttton.Style>
    <local:Buttton.Resources>
        <local:SampleConverter x:Key="converter" />
    </local:Buttton.Resources>
    abc
</local:Buttton>

長くなりますし Style だけ別なのもなんかイヤです


できればデフォルトのスタイルを そのクラス定義ファイルに書いておきたいのですが 要素の Resources プロパティでなく Application.Resources に定義しておくのが一般的みたいです

Buttton.xaml ファイルはなくしてしまって App.xaml にこう書きます
<Application.Resources>
    <Style TargetType="local:Buttton">
        <Setter Property="Background" Value="Orange"/>
    </Style>
</Application.Resources>

Buttton の Resources プロパティには何も入っていないので Window の方ではこうかけます
<local:Buttton>
    <local:Buttton.Resources>
        <local:SampleConverter x:Key="converter" />
        <Style TargetType="local:Buttton" BasedOn="{StaticResource {x:Type local:Buttton}}">
            <Setter Property="Foreground" Value="Blue"/>
        </Style>
    </local:Buttton.Resources>
    abc
</local:Buttton>

この場合も BasedOn がないと適用されるスタイルはここに書いた青色文字だけになって 背景色がなくなりますので注意です


Style や Resources を使わずに直接プロパティを指定した場合は 適用されたスタイルにプロパティ設定したものを上書きするように両方が適用されます
<local:Buttton Foreground="Blue">
    abc
</local:Buttton>
だと 背景も文字色もあります

ですが ひとつひとつに設定していかないといけないのは不便ですよね

ResourceDictionary

App.xaml の Application.Resources にデフォルトスタイルを書くとしても 全部ここに書いたらすごく長くなるし あれこれ混ざって見づらいです

分けて書きたい ってときには ResourceDictionary が使えます
よくあるファイル分割です

パーツとなる XAML のルートは ResourceDictionary にします
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:liblib.wpf">
    <Style TargetType="Button">
        <Setter Property="Foreground" Value="Orange" />
    </Style>
    <Color x:Key="Red">#fe4060</Color>
</ResourceDictionary>
ResourceDictionary の中には .Resources と同じく Style などを置いておけます


ロードする側は .Resources に ResourceDictionary を Source プロパティ付きでいれます
<Application 略>
    <Application.Resources>
        <ResourceDictionary Source="Parts1.xaml" />
    </Application.Resources>
</Application>

複数をまとめたいなら ResourceDictionary の MergedDictionaries プロパティに ResourceDictionary をいれます
<Window 略>
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Parts1.xaml"/>
                <ResourceDictionary Source="Parts2.xaml"/>
                <ResourceDictionary Source="Parts3.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    <Window.Resources>
</Window>

Source プロパティ付きの ResourceDictionary は子要素にリソースをもつことができないです
Source とその場で書いたリソースをまとめたいなら MergedDictionaries で Source 付きと直接リソース定義したものをマージします
<Window 略>
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Parts1.xaml"/>
                <ResourceDictionary>
                    <Style TargetType="Label">
                        <Setter Property="Foreground" Value="HotPink" />
                    </Style>
                </ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    <Window.Resources>
</Window>

MergedDictionaries プロパティがあるときも Source プロパティがあるのと一緒で こういう直接リソースかくことはできません
<Window 略>
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Parts1.xaml"/>
            </ResourceDictionary.MergedDictionaries>
            <Style TargetType="Label">
                <Setter Property="Foreground" Value="Blue" />
            </Style>
        </ResourceDictionary>
    <Window.Resources>
</Window>

それと .Resources の中に ResourceDictionary があるときに 直接他のリソース定義もできません
<Window 略>
    <Window.Resources>
        <ResourceDictionary>
        </ResourceDictionary>
        <Style TargetType="Label">
            <Setter Property="Foreground" Value="Blue" />
        </Style>
    <Window.Resources>
</Window>

別アセンブリ

Source 指定で ResourceDictionary を取得するときに別アセンブリも指定できます
<Application 略>
    <Application.Resources>
        <ResourceDictionary Source="pack://application:,,,/liblib;component/src/wpf/resource.xaml"/>
    </Application.Resources>
</Application>

「liblib」 がアセンブリ名です
「src/wpf/resource.xaml」 がそのアセンブリのプロジェクトルートからのファイルのパスです
プロジェクトのルートに src フォルダがあって wpf フォルダがあって resource.xaml というファイルがある場合です

「component」 もパスの一部に見えますが ここはパスじゃないです
別アセンブリを表す URI に必要なものです