把常用的顏色、間距、字型、邊角半徑集中管理:
<Window.Resources>
<!-- 調色盤 -->
<Color x:Key="PrimaryColor">#FF2B6CB0</Color>
<Color x:Key="AccentColor">#FF0EA5E9</Color>
<SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource PrimaryColor}"/>
<SolidColorBrush x:Key="AccentBrush" Color="{StaticResource AccentColor}"/>
<SolidColorBrush x:Key="TextBrush" Color="#222222"/>
<SolidColorBrush x:Key="MutedTextBrush" Color="#666666"/>
<SolidColorBrush x:Key="PanelBrush" Color="#F7F9FC"/>
<!-- 間距與圓角 -->
<x:Double x:Key="Radius">6</x:Double>
<Thickness x:Key="Gap">12</Thickness>
<Thickness x:Key="CellPadding">6,4</Thickness>
<!-- 字型大小 -->
<x:Double x:Key="TitleSize">20</x:Double>
<x:Double x:Key="BodySize">14</x:Double>
</Window.Resources>
StaticResource
:載入時解析,效能較佳;適用較少變化的資源。DynamicResource
:執行期可變更(例如切換 Light/Dark 主題)。<Window.Resources>
<Style x:Key="PrimaryButton" TargetType="Button">
<Setter Property="Background" Value="{StaticResource PrimaryBrush}"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Padding" Value="12,8"/>
<Setter Property="FontSize" Value="{StaticResource BodySize}"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
CornerRadius="{StaticResource Radius}">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="PART_Border" Property="Background"
Value="{StaticResource AccentBrush}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.5"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<!-- 使用 -->
<Button Style="{StaticResource PrimaryButton}" Content="下載股票"/>
注意:若在
ControlTemplate
使用Border
並需要觸發器指到該元素,請給它x:Name="PART_Border"
,上例可再補上 Name 後於 Trigger 使用TargetName
。
對指定型別全域生效、無需 x:Key:
<Window.Resources>
<Style TargetType="TextBox">
<Setter Property="Margin" Value="0,0,0,8"/>
<Setter Property="Padding" Value="8,6"/>
<Setter Property="FontSize" Value="{StaticResource BodySize}"/>
<Setter Property="BorderBrush" Value="#DDDDDD"/>
<Setter Property="BorderThickness" Value="1"/>
</Style>
</Window.Resources>
<!-- 所有 TextBox 都會套用 -->
<TextBox Text="{Binding Query}" />
專案結構建議:
/Styles
Colors.xaml
Typography.xaml
Controls.Buttons.xaml
Controls.DataGrid.xaml
Theme.Light.xaml
Theme.Dark.xaml
在 App.xaml
合併:
<Application ...>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles/Colors.xaml"/>
<ResourceDictionary Source="Styles/Typography.xaml"/>
<ResourceDictionary Source="Styles/Controls.Buttons.xaml"/>
<ResourceDictionary Source="Styles/Controls.DataGrid.xaml"/>
<ResourceDictionary Source="Styles/Theme.Light.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
好處:集中資源、跨視窗共用、切換主題更容易。
建立 Styles/Controls.DataGrid.xaml
:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- 行為一致化 -->
<Style TargetType="DataGrid">
<Setter Property="AutoGenerateColumns" Value="False"/>
<Setter Property="HeadersVisibility" Value="Column"/>
<Setter Property="GridLinesVisibility" Value="None"/>
<Setter Property="RowHeaderWidth" Value="0"/>
<Setter Property="CanUserAddRows" Value="False"/>
<Setter Property="CanUserDeleteRows" Value="False"/>
<Setter Property="CanUserReorderColumns" Value="True"/>
<Setter Property="CanUserResizeColumns" Value="True"/>
<Setter Property="CanUserSortColumns" Value="True"/>
<Setter Property="RowBackground" Value="White"/>
<Setter Property="AlternatingRowBackground" Value="#FAFAFA"/>
<Setter Property="RowHeight" Value="32"/>
<Setter Property="ColumnHeaderHeight" Value="36"/>
<Setter Property="HorizontalGridLinesBrush" Value="#EEEEEE"/>
<Setter Property="VerticalGridLinesBrush" Value="#EEEEEE"/>
<Setter Property="Foreground" Value="{StaticResource TextBrush}"/>
<Setter Property="BorderBrush" Value="#E6EAF0"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CellStyle">
<Setter.Value>
<Style TargetType="DataGridCell">
<Setter Property="Padding" Value="{StaticResource CellPadding}"/>
<Setter Property="BorderThickness" Value="0"/>
</Style>
</Setter.Value>
</Setter>
<Setter Property="ColumnHeaderStyle">
<Setter.Value>
<Style TargetType="DataGridColumnHeader">
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Foreground" Value="{StaticResource MutedTextBrush}"/>
<Setter Property="Background" Value="{StaticResource PanelBrush}"/>
<Setter Property="Padding" Value="8,4"/>
<Setter Property="BorderBrush" Value="#E6EAF0"/>
<Setter Property="BorderThickness" Value="0,0,0,1"/>
</Style>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
使用時只要宣告 DataGrid,樣式會自動套用(隱式樣式)。
DropShadowEffect
(慎用,成本高),或用背景/邊框營造層級。建立 Theme.Light.xaml
與 Theme.Dark.xaml
兩套資源,只差在顏色刷子值:
Theme.Light.xaml
:
<SolidColorBrush x:Key="WindowBgBrush" Color="#FFFFFF"/>
<SolidColorBrush x:Key="TextBrush" Color="#222222"/>
<SolidColorBrush x:Key="PanelBrush" Color="#F7F9FC"/>
Theme.Dark.xaml
:
<SolidColorBrush x:Key="WindowBgBrush" Color="#1F2430"/>
<SolidColorBrush x:Key="TextBrush" Color="#EAEAEA"/>
<SolidColorBrush x:Key="PanelBrush" Color="#2A3040"/>
切換主題(程式碼側)做法:
Application.Current.Resources.MergedDictionaries
最後一筆主題資源。DynamicResource
綁定顏色處處即時更新)。<DockPanel Background="{DynamicResource WindowBgBrush}">
<StackPanel Orientation="Horizontal" DockPanel.Dock="Top" Margin="{StaticResource Gap}">
<TextBox Width="220" />
<Button Style="{StaticResource PrimaryButton}" Content="下載股票" Margin="8,0,0,0"/>
<Button Content="載入本地" Margin="8,0,0,0"/>
</StackPanel>
<DataGrid ItemsSource="{Binding Stocks}" Margin="{StaticResource Gap}">
<DataGrid.Columns>
<DataGridTextColumn Header="代號" Binding="{Binding Code}" Width="100"/>
<DataGridTextColumn Header="名稱" Binding="{Binding Name}" Width="200"/>
<DataGridTextColumn Header="產業" Binding="{Binding Industry}" Width="*"/>
</DataGrid.Columns>
</DataGrid>
</DockPanel>
MergedDictionaries
中被替換,而非在控制項本地覆蓋。Style
統一控制項外觀,抽離到 ResourceDictionary。DynamicResource
即時換膚。