Следует уяснить, что классы
Animation
могут подключаться к любому
свойству зависимости заданного объекта, которое имеет соответствующий тип. Как объяснялось в главе 25, свойства зависимости являются специальной формой свойств, которую требуют многие службы WPF, включая анимацию, привязку данных и стили.
По соглашению свойство зависимости определяется как статическое, доступное только для чтения поле класса, имя которого образуется добавлением слова
Property
к нормальному имени свойства. Например, для обращения к свойству зависимости для свойства
Height
класса
Button
в коде будет использоваться
Button.HeightProperty
.
Свойства То, From и By
Во всех классах
Animation
определены следующие ключевые свойства, которые управляют начальным и конечным значениями, применяемыми для выполнения анимации:
•
То
— представляет конечное значение анимации;
•
From
— представляет начальное значение анимации;
•
By
— представляет общую величину, на которую анимация изменяет начальное значение.
Несмотря на тот факт, что все классы поддерживают свойства
То
,
From
и
By
, они не получают их через виртуальные члены базового класса. Причина в том, что лежащие в основе типы, упакованные внутри указанных свойств, варьируются в широких пределах (целые числа, цвета, объекты
Thickness
и т.д.), и представление всех возможностей через единственный базовый класс привело бы к очень сложным кодовым конструкциям.
В связи со сказанным может возникнуть вопрос: почему не использовались обобщения .NET для определения единственного обобщенного класса анимации с одиночным параметром типа (скажем,
Animate<T>
)? Опять-таки, поскольку существует огромное количество типов данных (цвета, векторы, целые числа, строки и т.д.), применяемых для анимации свойств зависимости, решение оказалось бы не настолько ясным, как можно было бы ожидать (не говоря уже о том, что XAML обеспечивает лишь ограниченную поддержку обобщенных типов).
Роль базового класса Timeline
Хотя для определения виртуальных свойств
То
,
From
и
By
не использовался единственный базовый класс, классы
Animation
все же разделяют общий базовый класс —
System.Windows.Media.Animation.Timeline
. Данный тип предлагает набор дополнительных свойств, которые управляют темпом продвижения анимации (табл. 27.1).
Реализация анимации в коде C#
Вы построите окно, содержащее элемент
Button
, который обладает довольно странным поведением: когда на него наводится курсор мыши, он вращается вокруг своего левого верхнего угла. Начните с создания в Visual Studio нового проекта приложения WPF по имени
SpinningButtonAnimationApp
. Модифицируйте начальную разметку, как показано ниже (обратите внимание на обработку события
MouseEnter
кнопки):
<Button x:Name="btnSpinner" Height="50" Width="100" Content="I Spin!"
MouseEnter="btnSpinner_MouseEnter" Click="btnSpinner_OnClick"/>
В файле отделенного кода импортируйте пространство имен
System.Windows.Media.Animation
и добавьте в файл C# следующий код:
private bool _isSpinning=false;
private void btnSpinner_MouseEnter(
object sender, MouseEventArgs e)
{
if (!_isSpinning)
{
_isSpinning=true;
<b> // Создать объект DoubleAnimation и зарегистрировать</b>
<b> // его с событием Completed.</b>
var dblAnim=new DoubleAnimation();
dblAnim.Completed +=(o, s)=> { _isSpinning=false; };
<b> // Установить начальное и конечное значения.</b>
dblAnim.From=0;
dblAnim.To=360;
<b> // Создать объект RotateTransform и присвоить</b>
<b> // его свойству RenderTransform кнопки.</b>
var rt=new RotateTransform();
btnSpinner.RenderTransform=rt;
<b> // Выполнить анимацию объекта RotateTransform.</b>
rt.BeginAnimation(RotateTransform.AngleProperty, dblAnim);
}
}
private void btnSpinner_OnClick(
object sender, RoutedEventArgs e)
{
}
Первая крупная задача метода
btnSpinner_MouseEnter()
связана с конфигурированием объекта
DoubleAnimation
, который будет начинать со значения
0
и заканчивать значением
360
. Обратите внимание, что для этого объекта также обрабатывается событие
Completed
, где переключается булевская переменная уровня класса, которая применяется для того, чтобы выполняющаяся анимация не была сброшена в начало.
Затем создается объект
RotateTransform
, который подключается к свойству
RenderTransform
элемента управления
Button
(
btnSpinner
). Наконец, объект
RenderTransform
информируется о начале анимации его свойства
Angle
с использованием объекта
DoubleAnimation
. Реализация анимации в коде обычно осуществляется путем вызова метода
BeginAnimation()
и передачи ему лежащего в основе
свойства зависимости, к которому необходимо применить анимацию (вспомните, что по соглашению оно определено как статическое поле класса), и связанного объекта анимации.