Introduction to WinUI 3 Styling
WinUI 3 offers a robust and flexible styling system that allows you to customize the appearance of your application to match your brand identity or user preferences. This section dives deep into the core concepts and techniques for styling your WinUI 3 applications.
Styling in WinUI 3 is primarily achieved through the use of XAML resources, styles, templates, and themes. By leveraging these powerful features, you can create visually appealing and consistent user experiences.
Themes
Themes define the overall look and feel of your application, influencing colors, fonts, and spacing. WinUI 3 supports different theme variants that users can choose from, such as Light, Dark, and High Contrast.
Theme Resources
Theme resources are values that change based on the active theme. These are typically defined in your application's resource dictionary and can include brushes, colors, thicknesses, and other visual properties.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Light Theme Colors -->
<SolidColorBrush x:Key="SystemAccentColor" Color="#0078D4"/>
<SolidColorBrush x:Key="WindowBackgroundBrush" Color="White"/>
<SolidColorBrush x:Key="TextFillColorPrimary" Color="Black"/>
<!-- Dark Theme Colors -->
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="SystemAccentColor" Color="#0096FF"/>
<SolidColorBrush x:Key="WindowBackgroundBrush" Color="#1E1E1E"/>
<SolidColorBrush x:Key="TextFillColorPrimary" Color="White"/>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush x:Key="SystemAccentColor" Color="Black"/>
<SolidColorBrush x:Key="WindowBackgroundBrush" Color="White"/>
<SolidColorBrush x:Key="TextFillColorPrimary" Color="Black"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
Application Theme
You can programmatically set or respond to changes in the application's theme. The Application.Current.RequestedTheme property allows you to control this.
Styles
Styles are reusable sets of property values that can be applied to UI elements. They are fundamental to creating a consistent look and feel across your application.
Base Styles
WinUI 3 provides default styles for all its controls. These base styles define the standard appearance and behavior of elements like buttons, text boxes, and grids.
Custom Styles
You can define your own styles to override default appearances or to create unique looks for specific elements.
<!-- In your App.xaml or a separate ResourceDictionary -->
<Style TargetType="Button" x:Key="MyPrimaryButtonStyle">
<Setter Property="Background" Value="{StaticResource SystemAccentColor}"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Padding" Value="12, 6"/>
<Setter Property="CornerRadius" Value="4"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<!-- Add event handlers or other properties as needed -->
</Style>
To apply this style:
<Button Content="Click Me" Style="{StaticResource MyPrimaryButtonStyle}"/>
Style Inheritance
Styles can inherit from other styles, allowing you to build upon existing definitions and avoid repetition. This is done using the BasedOn attribute.
<Style TargetType="Button" x:Key="MySecondaryButtonStyle" BasedOn="{StaticResource MyPrimaryButtonStyle}">
<Setter Property="Background" Value="{ThemeResource SecondaryAccentColor}"/>
<Setter Property="Foreground" Value="Black"/>
</Style>
Templates
Templates define the visual structure and behavior of controls, allowing for complete customization of their appearance.
Control Templates
Control templates define how a control is rendered. They often involve a hierarchy of visual elements, including `Grid`, `StackPanel`, `TextBlock`, `Path`, etc.
Example (simplified):
<Style TargetType="ToggleButton" x:Key="CustomCheckboxStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<TextBlock Text=""
Foreground="{TemplateBinding Foreground}"
FontSize="16"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Visibility="{TemplateBinding IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<TextBlock Text=""
Foreground="{TemplateBinding Foreground}"
FontSize="16"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Visibility="{TemplateBinding IsChecked, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWayInverse}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Data Templates
Data templates define how data items are displayed in UI elements like `ListView` or `GridView`. They are crucial for presenting collections of information in a visually organized manner.
<DataTemplate x:Key="PersonDataTemplate">
<Grid Padding="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Ellipse Width="40" Height="40" Fill="{Binding ProfilePictureBrush}"/>
<StackPanel Grid.Column="1" Margin="10,0,0,0">
<TextBlock Text="{Binding Name}" FontSize="16" FontWeight="SemiBold"/>
<TextBlock Text="{Binding Title}" Foreground="Gray"/>
</StackPanel>
</Grid>
</DataTemplate>
Resources
Resources are XAML objects that can be defined once and reused across your application. This promotes efficiency and maintainability.
Dynamic Resources
Dynamic resources are resolved at runtime. If the value of a dynamic resource changes, all elements using it are automatically updated. This is ideal for theme-dependent values.
<TextBlock Text="Welcome" Foreground="{DynamicResource SystemAccentColor}"/>
Static Resources
Static resources are resolved at compile time. They offer better performance than dynamic resources when the values are not expected to change.
<Button Content="Save" Background="{StaticResource MyPrimaryButtonStyle.Background}"/>
Visual States
Visual states allow controls to change their appearance based on their current state (e.g., `Normal`, `PointerOver`, `Pressed`, `Disabled`). These are defined within a `ControlTemplate` using `VisualStateManager`.
Example snippet within a `ControlTemplate`:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<ColorAnimation To="{ThemeResource SystemAccentColor}"
Duration="0"
Storyboard.TargetProperty="(Button.Background).(SolidColorBrush.Color)"
Storyboard.TargetName="Border"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation To="{ThemeResource SystemAccentColor}"
Duration="0"
Storyboard.TargetProperty="(Button.Background).(SolidColorBrush.Color)"
Storyboard.TargetName="Border"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
Customization Examples
Here are a few common customization scenarios:
Note on Customization
When customizing controls, it's often best to create derived styles rather than modifying the default styles directly to maintain compatibility with future WinUI updates.
Changing Button Corner Radius
Apply a custom style to change the corner radius of buttons.
<Style TargetType="Button" x:Key="RoundedButton" BasedOn="{StaticResource ButtonRevealStyle}">
<Setter Property="CornerRadius" Value="12"/>
</Style>
Customizing ListView Item Appearance
Use a `DataTemplate` to define the layout and styling for each item in a `ListView`.
<ListView ItemsSource="{x:Bind MyItems}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:MyDataItem">
<StackPanel Orientation="Horizontal" Padding="5">
<SymbolIcon Symbol="{x:Bind Symbol}"/>
<TextBlock Text="{x:Bind Name}" Margin="10,0,0,0"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>