<DoubleAnimation From="12" To="100" Duration="0:0:4"
RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Label.Triggers>
</Label>
Рассмотрим еще один пример определения анимации в XAML, на этот раз анимации ключевыми кадрами.
Анимация с использованием дискретных ключевых кадров
В отличие от объектов анимации линейной интерполяцией, обеспечивающих только перемещение между начальной и конечной точками, объекты анимации ключевыми кадрами позволяют создавать коллекции специальных значений, которые должны достигаться в определенные моменты времени.
Чтобы проиллюстрировать применение типа дискретного ключевого кадра, предположим, что необходимо построить элемент управления Button, который выполняет анимацию своего содержимого так, что на протяжении трех секунд появляется значение ОК! по одному символу за раз. Представленная далее разметка находится в файле StringAnimation.xaml. Ее можно скопировать в редактор Kaxaml и просмотреть результаты.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="100" Width="300"
WindowStartupLocation="CenterScreen" Title="Animate String Data!">
<StackPanel>
<Button Name="myButton" Height="40"
FontSize="16pt" FontFamily="Verdana" Width="100">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Loaded">
<BeginStoryboard>
<Storyboard>
<StringAnimationUsingKeyFrames RepeatBehavior="Forever"
Storyboard.TargetProperty="Content"
Duration="0:0:3">
<DiscreteStringKeyFrame Value="" KeyTime="0:0:0" />
<DiscreteStringKeyFrame Value="O" KeyTime="0:0:1" />
<DiscreteStringKeyFrame Value="OK" KeyTime="0:0:1.5" />
<DiscreteStringKeyFrame Value="OK!" KeyTime="0:0:2" />
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})
</StringAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Window>
Первым делом обратите внимание, что для кнопки определяется триггер события, который обеспечивает запуск раскадровки при загрузке кнопки в память. Класс StringAnimationUsingKeyFrames отвечает за изменение содержимого кнопки через значение Storyboard.TargetProperty.
Внутри элемента StringAnimationUsingKeyFrames определены четыре элемента DiscreteStringKeyFrame, которые изменяют свойство Content на протяжении двух секунд (длительность, установленная объектом StringAnimationUsingKeyFrames, составляет в сумме три секунды, поэтому между финальным символом ! и следующим появлением О будет заметна небольшая пауза).
Теперь, когда вы получили некоторое представление о том, как строятся анимации в коде C# и разметке XAML, давайте выясним роль стилей WPF, которые интенсивно задействуют графику, объектные ресурсы и анимацию.
Роль стилей WPF
При построении пользовательского интерфейса приложения WPF нередко требуется обеспечить общий вид и поведение для целого семейства элементов управления. Например, может понадобиться сделать так, чтобы все типы кнопок имели ту же самую высоту, ширину, цвет и размер шрифта для своего строкового содержимого. Хотя решить задачу можно было бы установкой идентичных значений в индивидуальных свойствах, такой подход затрудняет внесение изменений, потому что при каждом изменении придется переустанавливать один и тот же набор свойств во множестве объектов.
К счастью, инфраструктура WPF предлагает простой способ ограничения внешнего вида и поведения связанных элементов управления с использованием стилей. Выражаясь просто, стиль WPF — это объект, который поддерживает коллекцию пар "свойство-значение". С точки зрения программирования отдельный стиль представляется с помощью класса System.Windows.Style. Класс Style имеет свойство по имени Setters, которое открывает доступ к строго типизированной коллекции объектов Setter. Именно объект Setter обеспечивает возможность определения пар "свойство-значение".
В дополнение к коллекции Setters класс Style также определяет несколько других важных членов, которые позволяют встраивать триггеры, ограничивать место применения стиля и даже создавать новый стиль на основе существующего (воспринимайте такой прием как "наследование стилей"). Ниже перечислены наиболее важные члены класса Style: