This article is currently in the process of being translated into Russian (~99% done).
Trigger, DataTrigger & EventTrigger
До сих пор мы работали со стилями посредством установки статического значения для конкретного свойства. Однако, используя триггеры, Вы можете изменить значения данного свойства, при изменении определенных условий. Существует несколько разновидностей триггеров: триггеры свойств, триггеры событий и триггеры данных. Они позволяют вам реализовывать функционал, который в обычных условиях был бы выполнен в CodeBehind (процес сепарации при разработке графического интерфейса и кода).
Триггер свойства
Наиболее часто используемым является триггер свойства, который в разметке определяется простым элементом <Trigger>. Он ждет, пока выбранное свойство элемента управления не изменится согласно установленым правилам и, после совпадения, модифицирует необходимые свойства.
<Window x:Class="WpfTutorialSamples.Styles.StyleTriggersSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="StyleTriggersSample" Height="100" Width="300">
<Grid>
<TextBlock Text="Hello, styled world!" FontSize="28" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Blue"></Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Red" />
<Setter Property="TextDecorations" Value="Underline" />
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</Window>
В этом стиле, мы изменили цвет кисти переднего плана (Foreground), чтобы текст выглядел как гиперссылка. После этого был добавлен триггер, следящий за свойством IsMouseOver. Как только это свойство принимает значение True (курсор находится на элементе), мы устанавливаем два свойства (c помощью Setter): меняем Foreground на красный и используем подчеркивание. Это отличный пример того, что использовать триггеры для модификации интерфейса очень просто, и нет необходимости работать с CodeBehind.
Мы определили локальный стиль для выбранного TextBlock, но как было показано ранее, стили могут быть определены глобально, например для всех элементов TextBlock в приложении.
Триггер данных
Триггеры данных, представленные элементом <DataTrigger>, используются для свойств, которые не обязательно должны являться зависимыми. Они функционируют путем связывания обыкновенного свойства, состояние которого далее будет отслеживаться. Они так же дают возможность связывать Ваш триггер со свойствами других элементов управления. Обратите внимание на следующий код:
<Window x:Class="WpfTutorialSamples.Styles.StyleDataTriggerSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="StyleDataTriggerSample" Height="200" Width="200">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<CheckBox Name="cbSample" Content="Hello, world?" />
<TextBlock HorizontalAlignment="Center" Margin="0,20,0,0" FontSize="48">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="No" />
<Setter Property="Foreground" Value="Red" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=cbSample, Path=IsChecked}" Value="True">
<Setter Property="Text" Value="Yes!" />
<Setter Property="Foreground" Value="Green" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
</Window>
В этом примере у нас было два элемента: CheckBox и TextBlock. С помощью DataTrigger мы осуществили привязку текстового поля к свойству IsChecked CheckBox'а. После этого, определили стиль по умолчанию, в котором TextBlock содержит текст "No" красного цвета. Далее, используя триггер данных, мы модифицировали стиль для случая, когда свойство IsChecked меняется на True - изменили текст на зеленый с содержанием "Yes!" (как на скриншоте выше).
Триггер событий
Триггеры событий, определенные элементом <EventTrigger>, являются наиболее распространенными триггерами для анимации элемента, на котором он сработал. На данный момент мы еще не обсуждали анимацию, но чтобы продемонстрировать работу триггера, мы используем ее. Подробности на тему анимации Вы найдете в последующих разделах. Возвращаясь к триггерам, вот пример:
<Window x:Class="WpfTutorialSamples.Styles.StyleEventTriggerSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="StyleEventTriggerSample" Height="100" Width="300">
<Grid>
<TextBlock Name="lblStyled" Text="Hello, styled world!" FontSize="18" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.300" Storyboard.TargetProperty="FontSize" To="28" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.800" Storyboard.TargetProperty="FontSize" To="18" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</Window>
Разметка выглядит весьма вызывающе, но если Вы запустите пример, то посмотрите на результат, заметьте, что в итоге мы получили отличную анимацию движения в ~20 линий кода XAML. Как можно заменить, здесь я использовал EventTrigger для подписки на два события: MouseEnter и MouseLeave. Когда курсор мыши попадает на элемент, осуществляется плавный переход к размеру шрифта 28 пикселей в течение 300 миллисекунд. Курсор покидает элемент, и шрифт меняется на 18 пикселей, но медленнее, что, по-моему неплохо выглядит.
Резюмируя
Стили WPF делают процесс разработки интерфейса последовательным, а с помощью триггеров этот интерфейс становится динамическим. Стили это очень удобное решение, но еще удобнее оно становится при использовании, например, шаблона элементов. На эту тему можно прочитать больше в рамках данного руководства.
В следующей главе мы рассмотрим Мультитриггеры, которые позволят нам применять стили на основе нескольких условий.