Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public class AnimatableHelperBase<T>
- {
- // Это attached property OriginalProperty. К нему мы будем привязывать свойство из VM,
- // и получать нотификацию об его изменении
- public static T GetOriginalProperty(DependencyObject obj) =>
- (T)obj.GetValue(OriginalPropertyProperty);
- public static void SetOriginalProperty(DependencyObject obj, T value) =>
- obj.SetValue(OriginalPropertyProperty, value);
- public static readonly DependencyProperty OriginalPropertyProperty =
- DependencyProperty.RegisterAttached(
- "OriginalProperty", typeof(T), typeof(AnimatableHelperBase<T>),
- new PropertyMetadata(OnOriginalUpdatedStatic));
- // это "производное" attached property, которое будет
- // анимированно "догонять" OriginalProperty
- public static T GetAnimatedProperty(DependencyObject obj) =>
- (T)obj.GetValue(AnimatedPropertyProperty);
- public static void SetAnimatedProperty(DependencyObject obj, T value) =>
- obj.SetValue(AnimatedPropertyProperty, value);
- public static readonly DependencyProperty AnimatedPropertyProperty =
- DependencyProperty.RegisterAttached(
- "AnimatedProperty", typeof(T), typeof(AnimatableHelperBase<T>));
- // это вызывается когда значение OriginalProperty меняется
- static void OnOriginalUpdatedStatic(DependencyObject o, DependencyPropertyChangedEventArgs e)
- {
- T newValue = (T)e.NewValue;
- // находим элемент, на котором меняется свойство
- FrameworkElement self = (FrameworkElement)o;
- AnimationTimeline animation = CreateAnimation(self, newValue);
- self.BeginAnimation(AnimatedPropertyProperty, animation);
- }
- protected static Func<FrameworkElement, T, AnimationTimeline> CreateAnimation;
- }
- public class AnimatableDoubleHelper : AnimatableHelperBase<double>
- {
- static AnimatableDoubleHelper()
- {
- CreateAnimation = (self, newValue) =>
- new DoubleAnimation(newValue, new Duration(TimeSpan.FromSeconds(0.3)));
- }
- }
- public class AnimatablePointHelper : AnimatableHelperBase<Point>
- {
- static AnimatablePointHelper()
- {
- CreateAnimation = (self, newValue) =>
- new PointAnimation(newValue, new Duration(TimeSpan.FromSeconds(0.3)));
- }
- }
- --------------------
- class Tile : VM
- {
- (int x, int y) location;
- public (int x, int y) Location
- {
- get => location;
- set => Set(ref location, value);
- }
- string caption;
- public string Caption
- {
- get => caption;
- set => Set(ref caption, value);
- }
- }
- --------------------
- public MainVM()
- {
- Tiles = new ObservableCollection<Tile>
- {
- new Tile { Caption="1", Location = (0, 0) },
- new Tile { Caption="2", Location = (1, 0) },
- new Tile { Caption="3", Location = (2, 0) },
- new Tile { Caption="4", Location = (2, 1) },
- new Tile { Caption="5", Location = (2, 2) },
- new Tile { Caption="6", Location = (1, 2) },
- new Tile { Caption="7", Location = (0, 2) },
- new Tile { Caption="8", Location = (0, 1) },
- };
- turnCommand = new RelayCommand(_ => TurnTiles());
- }
- void TurnTiles()
- {
- // Здесь используются фичи C# 7.0 и .NET Framework 4.7
- Dictionary<(int, int), (int, int)> transitions = new Dictionary<(int, int), (int, int)>
- {
- [(0, 0)] = (0, 1),
- [(1, 0)] = (0, 0),
- [(2, 0)] = (1, 0),
- [(2, 1)] = (2, 0),
- [(2, 2)] = (2, 1),
- [(1, 2)] = (2, 2),
- [(0, 2)] = (1, 2),
- [(0, 1)] = (0, 2),
- };
- foreach (var tile in Tiles)
- tile.Location = transitions[tile.Location];
- }
- --------------------
- class XYToPointConverter : IValueConverter
- {
- public double TileWidth { get; set; }
- public double TileHeight { get; set; }
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- var typedValue = ((int x, int y))value;
- return new Point(typedValue.x * TileWidth, typedValue.y * TileHeight);
- }
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- throw new NotImplementedException();
- }
- }
- --------------------
- <Style>
- <Setter Property="local:AnimatablePointHelper.OriginalProperty"
- Value="{Binding Location, Converter={StaticResource XYToPointConverter}}"/>
- <Setter Property="Canvas.Left"
- Value="{Binding (local:AnimatablePointHelper.AnimatedProperty).X, RelativeSource={RelativeSource Self}}"/>
- <Setter Property="Canvas.Top"
- Value="{Binding (local:AnimatablePointHelper.AnimatedProperty).Y, RelativeSource={RelativeSource Self}}"/>
- </Style>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement