Стиль – это коллекция значений свойств, которые могут быть применены к элементу. Система стилей WPF играет ту же роль, что и CSS в HTML.
Ресурсы
Ресурсы предоставляют то же решение, что и стили, но они являются
громоздкими и не удобными. Так будет выглядеть объявление ресурса:
<!--Ресурсы окна -->
<Window.Resources>
<FontFamily x:Key="ButtonFontFamily">Times New Roman</FontFamily>
<sys:Double x:Key="ButtonFontSize">18</sys:Double>
<FontWeight x:Key="ButtonFontWeight">Bold</FontWeight>
</Window.Resources>
<StackPanel Margin="5">
<Button Padding="5" Margin="5"
FontFamily="{StaticResource ButtonFontFamily}"
FontWeight="{StaticResource ButtonFontWeight}"
FontSize="{StaticResource ButtonFontSize}">
Кнопка с настройками
</Button>
<TextBlock Margin="5">Обычный контент.</TextBlock>
<Button Padding="5" Margin="5">Обычная кнопка</Button>
<TextBlock Margin="5">Еще обычный контент.</TextBlock>
<Button Padding="5" Margin="5"
FontFamily="{StaticResource ButtonFontFamily}"
FontWeight="{StaticResource ButtonFontWeight}"
FontSize="{StaticResource ButtonFontSize}">
Кнопка с настройками
</Button>
</StackPanel>
Недостатки
• Нет никакого четкого признака, что все три ресурса связаны между собой. Это делает приложение менее удобным для дальнейшего сопровождения.
• Код разметки для применения такого подхода будет хранить слишком большое количество описаний.
Создание стиля
Определения объекта стиля в ресурсах окна:
<Window.Resources>
<!--Объявление стиля c ключом MyButtonStyle-->
<Style x:Key="MyButtonStyle">
<Setter Property="Button.FontFamily" Value="Times New Roman" />
<Setter Property="Button.FontSize" Value="18" />
<Setter Property="Button.FontWeight" Value="Bold" />
</Style>
</Window.Resources>
<StackPanel Margin="5">
<Button Padding="5" Margin="5" FontSize="24"
Style="{StaticResource MyButtonStyle}">
Кнопка со стилем
</Button>
<TextBlock Margin="5">Статический контент</TextBlock>
<Button Padding="5" Margin="5">Обычная кнопка</Button>
<TextBlock Margin="5">Статический контент</TextBlock>
<!--Каждый элемент управления WPF может использовать один стиль.
(Свойство Style определено в базовом классе FrameworlElement)-->
<Button Padding="5" Margin="5"
Style="{StaticResource MyButtonStyle}">
Кнопка со стилем
</Button>
</StackPanel>
Ключевые свойства стиля
Setters – коллекция объектов, которые автоматически устанавливают значение свойств элементов управления.
Triggers – коллекция объектов, которые позволяют автоматически изменять параметры стиля.
BasedOn – для создания стиля, который наследует другой стиль и переопределят его значения.
TargetType – указывает тип элементов на которые действует стиль.
Триггеры Triggers
Триггеры – декларативный подход к отслеживанию изменения по
определенному условию и применения соответствующего стиля.
Основные типы триггеров
Trigger – Самый простой триггер. Следит за изменением значения свойства.
MultiTrigger– Похож на первый но срабатывает при выполнении множества условий.
DataTriger – Срабатывает при изменении в связанных с ним данных.
MultiDataTrigger – множество триггеров данных.
EventTrigger– При возникновении события он применяет соответствующую анимацию.
Пример триггера:
<Window.Resources>
<Style x:Key="BigFontButtonStyle">
<Style.Setters>
<Setter Property="Control.FontFamily" Value="Times New Roman" />
<Setter Property="Control.FontSize" Value="18" />
</Style.Setters>
<!--Триггеры-->
<Style.Triggers>
<!--Если элемент в фокусе значение Foreground устанавливается как DarkRed-->
<Trigger Property="Control.IsFocused" Value="True">
<Setter Property="Control.Foreground" Value="Yellow" />
</Trigger>
<!--Если курсор находится над элементом, устанавливаются свойства Foreground и FontWeight-->
<Trigger Property="Control.IsMouseOver" Value="True">
<Setter Property="Control.Foreground" Value="Green" />
<Setter Property="Control.FontWeight" Value="Bold" />
</Trigger>
<!--Если курсор находится над элементом, устанавливаются свойства Foreground и FontWeight-->
<Trigger Property="Button.IsPressed" Value="True">
<Setter Property="Control.Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel Margin="5">
<Button Padding="5"
Margin="5"
Style="{StaticResource BigFontButtonStyle}">Кнопка со стилями и триггерами
</Button>
<TextBlock Margin="5">Обычный контент.</TextBlock>
<Button Padding="5"
Margin="5">
Обычная кнопка
</Button>
<TextBlock Margin="5">Обычный контент.</TextBlock>
<Button Padding="5"
Margin="5"
Style="{StaticResource BigFontButtonStyle}">
Кнопка со стилями и триггерами
</Button>
</StackPanel>
Пример мульти триггера. MultiTrigger
<Window.Resources>
<Style x:Key="MyButtonStyle">
<Style.Triggers>
<MultiTrigger>
<!--Список условий-->
<MultiTrigger.Conditions>
<Condition Property="Control.IsFocused" Value="True"></Condition>
<Condition Property="Control.IsMouseOver" Value="True"></Condition>
</MultiTrigger.Conditions>
<!--Список изменений, которые вступят в силу, если все условия выполнятся-->
<MultiTrigger.Setters>
<Setter Property="Control.Foreground" Value="DarkBlue"></Setter>
<Setter Property="Control.FontSize" Value="20"></Setter>
</MultiTrigger.Setters>
</MultiTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<Button Name="Button1" Style="{StaticResource MyButtonStyle}" Margin="20">
A Button
</Button>
<Button Name="Button2" Style="{StaticResource MyButtonStyle}" Margin="20">
A Button
</Button>
</StackPanel>
Пример MultiDataTrigger
<Window.Resources>
<!--В качестве ресурса используем класс-коллекцию из code behind-->
<c:Countries x:Key="PlacesData"/>
<!--Стиль для ListBoxItem-->
<Style TargetType="ListBoxItem">
<Style.Triggers>
<!--Если значение свойства ShortName объекта с этим стилем будет равно USA - текст станет красного цвета-->
<DataTrigger Binding="{Binding Path=ShortName}" Value="USA">
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
<!--Если значение свойства ShortName и Name будут равны значениям указаным в Value
то для элемента будет пременен стиль указаный в тэге Setter-->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=Name}" Value="Ukraine" />
<Condition Binding="{Binding Path=ShortName}" Value="UA" />
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="Cyan" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<TextBlock FontSize="18"
Margin="5"
FontWeight="Bold"
HorizontalAlignment="Center">
Пример работы с DataTrigger
</TextBlock>
<!--ListBox, который использует привязку.-->
<ListBox Width="180"
HorizontalAlignment="Center"
Background="Honeydew"
ItemsSource="{Binding Source={StaticResource PlacesData}}"/>
</StackPanel>
Пример EventTrigger
<Window.Resources>
<Style x:Key="BigFontButton">
<!--Стили-->
<Style.Setters>
<Setter Property="Control.FontFamily" Value="Times New Roman" />
<Setter Property="Control.FontSize" Value="18" />
<Setter Property="Control.FontWeight" Value="Bold" />
</Style.Setters>
<!--Триггеры
Обычные тригеры ожидают изменения свойств
EventTrigger - ожидает определенного события-->
<Style.Triggers>
<!--Действие на событие MouseEnter-->
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:0.2"
Storyboard.TargetProperty="FontSize"
To="22" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<!--Действие на событие MouseLeave-->
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:1"
Storyboard.TargetProperty="FontSize" To="18" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel Margin="5">
<Button Padding="5"
Margin="5"
Style="{StaticResource BigFontButton}">
Кнопка со стилем и триггерами
</Button>
<TextBlock Margin="5">Обычный контент.</TextBlock>
<Button Padding="5" Margin="5">
Обычная кнопка
</Button>
<TextBlock Margin="5">Еще один обычный контент.</TextBlock>
<Button Padding="5"
Margin="5"
Style="{StaticResource BigFontButton}">
Кнопка со стилем и триггерами
</Button>
</StackPanel>
