Guest User

Untitled

a guest
Aug 1st, 2017
82
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. public class AnimatableHelperBase<T>
  2. {
  3. // Это attached property OriginalProperty. К нему мы будем привязывать свойство из VM,
  4. // и получать нотификацию об его изменении
  5. public static T GetOriginalProperty(DependencyObject obj) =>
  6. (T)obj.GetValue(OriginalPropertyProperty);
  7. public static void SetOriginalProperty(DependencyObject obj, T value) =>
  8. obj.SetValue(OriginalPropertyProperty, value);
  9. public static readonly DependencyProperty OriginalPropertyProperty =
  10. DependencyProperty.RegisterAttached(
  11. "OriginalProperty", typeof(T), typeof(AnimatableHelperBase<T>),
  12. new PropertyMetadata(OnOriginalUpdatedStatic));
  13.  
  14. // это "производное" attached property, которое будет
  15. // анимированно "догонять" OriginalProperty
  16. public static T GetAnimatedProperty(DependencyObject obj) =>
  17. (T)obj.GetValue(AnimatedPropertyProperty);
  18. public static void SetAnimatedProperty(DependencyObject obj, T value) =>
  19. obj.SetValue(AnimatedPropertyProperty, value);
  20. public static readonly DependencyProperty AnimatedPropertyProperty =
  21. DependencyProperty.RegisterAttached(
  22. "AnimatedProperty", typeof(T), typeof(AnimatableHelperBase<T>));
  23.  
  24. // это вызывается когда значение OriginalProperty меняется
  25. static void OnOriginalUpdatedStatic(DependencyObject o, DependencyPropertyChangedEventArgs e)
  26. {
  27. T newValue = (T)e.NewValue;
  28. // находим элемент, на котором меняется свойство
  29. FrameworkElement self = (FrameworkElement)o;
  30. AnimationTimeline animation = CreateAnimation(self, newValue);
  31. self.BeginAnimation(AnimatedPropertyProperty, animation);
  32. }
  33.  
  34. protected static Func<FrameworkElement, T, AnimationTimeline> CreateAnimation;
  35. }
  36.  
  37. public class AnimatableDoubleHelper : AnimatableHelperBase<double>
  38. {
  39. static AnimatableDoubleHelper()
  40. {
  41. CreateAnimation = (self, newValue) =>
  42. new DoubleAnimation(newValue, new Duration(TimeSpan.FromSeconds(0.3)));
  43. }
  44. }
  45.  
  46. public class AnimatablePointHelper : AnimatableHelperBase<Point>
  47. {
  48. static AnimatablePointHelper()
  49. {
  50. CreateAnimation = (self, newValue) =>
  51. new PointAnimation(newValue, new Duration(TimeSpan.FromSeconds(0.3)));
  52. }
  53. }
  54.  
  55. --------------------
  56.  
  57. class Tile : VM
  58. {
  59. (int x, int y) location;
  60. public (int x, int y) Location
  61. {
  62. get => location;
  63. set => Set(ref location, value);
  64. }
  65.  
  66. string caption;
  67. public string Caption
  68. {
  69. get => caption;
  70. set => Set(ref caption, value);
  71. }
  72. }
  73.  
  74. --------------------
  75.  
  76. public MainVM()
  77. {
  78. Tiles = new ObservableCollection<Tile>
  79. {
  80. new Tile { Caption="1", Location = (0, 0) },
  81. new Tile { Caption="2", Location = (1, 0) },
  82. new Tile { Caption="3", Location = (2, 0) },
  83. new Tile { Caption="4", Location = (2, 1) },
  84. new Tile { Caption="5", Location = (2, 2) },
  85. new Tile { Caption="6", Location = (1, 2) },
  86. new Tile { Caption="7", Location = (0, 2) },
  87. new Tile { Caption="8", Location = (0, 1) },
  88. };
  89.  
  90. turnCommand = new RelayCommand(_ => TurnTiles());
  91. }
  92.  
  93. void TurnTiles()
  94. {
  95. // Здесь используются фичи C# 7.0 и .NET Framework 4.7
  96. Dictionary<(int, int), (int, int)> transitions = new Dictionary<(int, int), (int, int)>
  97. {
  98. [(0, 0)] = (0, 1),
  99. [(1, 0)] = (0, 0),
  100. [(2, 0)] = (1, 0),
  101. [(2, 1)] = (2, 0),
  102. [(2, 2)] = (2, 1),
  103. [(1, 2)] = (2, 2),
  104. [(0, 2)] = (1, 2),
  105. [(0, 1)] = (0, 2),
  106. };
  107. foreach (var tile in Tiles)
  108. tile.Location = transitions[tile.Location];
  109. }
  110.  
  111. --------------------
  112.  
  113. class XYToPointConverter : IValueConverter
  114. {
  115. public double TileWidth { get; set; }
  116. public double TileHeight { get; set; }
  117.  
  118. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  119. {
  120. var typedValue = ((int x, int y))value;
  121. return new Point(typedValue.x * TileWidth, typedValue.y * TileHeight);
  122. }
  123.  
  124. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  125. {
  126. throw new NotImplementedException();
  127. }
  128. }
  129.  
  130. --------------------
  131.  
  132. <Style>
  133. <Setter Property="local:AnimatablePointHelper.OriginalProperty"
  134. Value="{Binding Location, Converter={StaticResource XYToPointConverter}}"/>
  135. <Setter Property="Canvas.Left"
  136. Value="{Binding (local:AnimatablePointHelper.AnimatedProperty).X, RelativeSource={RelativeSource Self}}"/>
  137. <Setter Property="Canvas.Top"
  138. Value="{Binding (local:AnimatablePointHelper.AnimatedProperty).Y, RelativeSource={RelativeSource Self}}"/>
  139. </Style>
RAW Paste Data