Страницы

Поиск по вопросам

пятница, 26 октября 2018 г.

Анимация WPF при изменении свойства

Есть класс, представляющий игрока (привожу упрощенный вариант):
class Player : INotifyPropertyChanged { public string Name { get; }
int rank; public int Rank { get { return rank; } set { rank = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Rank")); } }
public event PropertyChangedEventHandler PropertyChanged;
public Player(string name) { Name = name; } }
Коллекция этих Players отображается, ну скажем, в ItemsControl:


Внешние силы меняют рейтинг игрока (не часто, не чаще 1 раза в несколько секунд).
Можно ли сделать средствами анимации WPF (не принципиально) так, чтобы при изменении рейтинга число в TextBox'е менялось плавно от текущего значения до нового, ну скажем, за 0.2 секунды?
Я могу, конечно, в сеттере запускать таймер, но это решение мне не нравится.


Ответ

Такой фичи из коробки нету, но её можно легко смастерить самостоятельно. Например, давайте заведём для этого attached property.
public static class AnimatableDoubleHelper { // Это attached property OriginalProperty. К нему мы будем привязывать свойство из VM, // и получать нотификацию об его изменении public static double GetOriginalProperty(DependencyObject obj) => (double)obj.GetValue(OriginalPropertyProperty); public static void SetOriginalProperty(DependencyObject obj, double value) => obj.SetValue(OriginalPropertyProperty, value); public static readonly DependencyProperty OriginalPropertyProperty = DependencyProperty.RegisterAttached( "OriginalProperty", typeof(double), typeof(AnimatableDoubleHelper), new PropertyMetadata(OnOriginalUpdated));
// это "производное" attached property, которое будет // анимированно "догонять" OriginalProperty public static double GetAnimatedProperty(DependencyObject obj) => (double)obj.GetValue(AnimatedPropertyProperty); public static void SetAnimatedProperty(DependencyObject obj, double value) => obj.SetValue(AnimatedPropertyProperty, value); public static readonly DependencyProperty AnimatedPropertyProperty = DependencyProperty.RegisterAttached( "AnimatedProperty", typeof(double), typeof(AnimatableDoubleHelper));
// это вызывается когда значение OriginalProperty меняется static void OnOriginalUpdated(DependencyObject o, DependencyPropertyChangedEventArgs e) { double newValue = (double)e.NewValue; // находим элемент, на котором меняется свойство FrameworkElement self = (FrameworkElement)o; DoubleAnimation animation = // создаём анимацию... new DoubleAnimation(newValue, new Duration(TimeSpan.FromSeconds(0.3))); // и запускаем её на AnimatedProperty self.BeginAnimation(AnimatedPropertyProperty, animation); } }
Как этим пользоваться? Очень просто. Пусть у нас был такой код:

Заменяем его на следующую конструкцию:

Получается вот что:

Комментариев нет:

Отправить комментарий