using System; using System.Collections; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; namespace Muchinfo.WPF.Controls.Animation { /// /// Class RollOverAnimation. /// [TemplatePart(Name = "NextItems", Type = typeof(ItemsControl))] [TemplatePart(Name = "CurrentItems", Type = typeof(ItemsControl))] public class RollOverAnimation : Control { static RollOverAnimation() { DefaultStyleKeyProperty.OverrideMetadata(typeof(RollOverAnimation), new FrameworkPropertyMetadata(typeof(RollOverAnimation))); } private const int C_steySeconds = 3; private const int C_PlaySeconds = 5; private Storyboard _rolloverStoryboard = new Storyboard(); private DoubleAnimationUsingKeyFrames _currentAnimation; private DoubleAnimationUsingKeyFrames _nextAnimation; private ItemsControl _currentItems, _nextItems; /// /// 当前索引 /// public int _currentIndex; public RollOverAnimation() { _currentAnimation = new DoubleAnimationUsingKeyFrames(); _nextAnimation = new DoubleAnimationUsingKeyFrames(); _rolloverStoryboard.Completed += _rolloverStoryboard_Completed; IsVisibleChanged += delegate(object sender, DependencyPropertyChangedEventArgs e) { if (false.Equals(e.NewValue)) { _rolloverStoryboard.Stop(this); } }; } /// /// 动画完成后切换 /// /// /// void _rolloverStoryboard_Completed(object sender, EventArgs e) { _rolloverStoryboard.Stop(this); PlayNextList(); _rolloverStoryboard.Begin(this, true); } /// /// 显示行的样式 /// public DataTemplate ItemsTemplate { get { return (DataTemplate)GetValue(ItemsTemplateProperty); } set { SetValue(ItemsTemplateProperty, value); } } // Using a DependencyProperty as the backing store for ItemsTemplate. This enables animation, styling, binding, etc... public static readonly DependencyProperty ItemsTemplateProperty = DependencyProperty.Register("ItemsTemplate", typeof(DataTemplate), typeof(RollOverAnimation), new PropertyMetadata(null)); /// /// 绑定的数据源 /// public IList ItemsSource { get { return (IList)GetValue(ItemsSourceProperty); } set { SetValue(ItemsSourceProperty, value); } } // Using a DependencyProperty as the backing store for ItemsSource. This enables animation, styling, binding, etc... public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IList), typeof(RollOverAnimation), new PropertyMetadata(null, OnItemsSourceChange)); /// /// 当前显示的项 /// public IList CurrentList { get { return (IList)GetValue(CurrentListProperty); } set { SetValue(CurrentListProperty, value); } } // Using a DependencyProperty as the backing store for CurrentList. This enables animation, styling, binding, etc... public static readonly DependencyProperty CurrentListProperty = DependencyProperty.Register("CurrentList", typeof(IList), typeof(RollOverAnimation), new PropertyMetadata(null)); /// /// 即将显示的项 /// public IList NextList { get { return (IList)GetValue(NextListProperty); } set { SetValue(NextListProperty, value); } } // Using a DependencyProperty as the backing store for NextList. This enables animation, styling, binding, etc... public static readonly DependencyProperty NextListProperty = DependencyProperty.Register("NextList", typeof(IList), typeof(RollOverAnimation), new PropertyMetadata(null)); /// /// 每次显示的数量 /// public int ShowCount { get { return (int)GetValue(ShowCountProperty); } set { SetValue(ShowCountProperty, value); } } // Using a DependencyProperty as the backing store for ShowIndex. This enables animation, styling, binding, etc... public static readonly DependencyProperty ShowCountProperty = DependencyProperty.Register("ShowCount", typeof(int), typeof(RollOverAnimation), new PropertyMetadata(3)); /// /// 当数据源改变时重新进行动画 /// /// /// public static void OnItemsSourceChange(DependencyObject d, DependencyPropertyChangedEventArgs e) { var self = d as RollOverAnimation; if (self != null) { self.InitSourceAndPlay(); } } /// /// 初始化数据并运行动画 /// private void InitSourceAndPlay() { if (ItemsSource != null && ItemsSource.Count > 0) { _rolloverStoryboard.Stop(this); _currentIndex = 0; if (ItemsSource.Count > ShowCount) { var list = new List(); var nextlist = new List(); int nextIndex = ShowCount; for (int i = 0; i < ShowCount; i++) { list.Add(ItemsSource[i]); if (nextIndex < ItemsSource.Count) { nextlist.Add(ItemsSource[nextIndex]); nextIndex++; } } _currentIndex = ShowCount - 1; CurrentList = list; NextList = nextlist; _rolloverStoryboard.Begin(this, true); } else { CurrentList = ItemsSource; } } } /// /// 播放一下个动画 /// private void PlayNextList() { if (ItemsSource != null) { CurrentList = NextList; int tempflag = _currentIndex + NextList.Count; _currentIndex = tempflag > ItemsSource.Count - 1 ? NextList.Count - 1 : tempflag; //if (_currentIndex >= ItemsSource.Count-1) //{ // _currentIndex = 0; //} tempflag = _currentIndex >= ItemsSource.Count - 1 ? 0 : _currentIndex + 1; var nextList = new List(); for (int i = tempflag; i < tempflag + ShowCount; i++) { if (i < ItemsSource.Count) { nextList.Add(ItemsSource[i]); } } NextList = nextList; } } public override void OnApplyTemplate() { _currentItems = GetTemplateChild("CurrentItems") as ItemsControl; _nextItems = GetTemplateChild("NextItems") as ItemsControl; base.OnApplyTemplate(); } protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) { if (_currentItems != null && _nextItems != null) { _currentAnimation.KeyFrames.Clear(); _currentAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0)))); _currentAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(C_steySeconds)))); _currentAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(-this.ActualHeight, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(C_PlaySeconds)))); _nextAnimation.KeyFrames.Clear(); _nextAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(this.ActualHeight, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0)))); _nextAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(this.ActualHeight, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(C_steySeconds)))); _nextAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(C_PlaySeconds)))); Storyboard.SetTarget(_currentAnimation, _currentItems); Storyboard.SetTargetProperty(_currentAnimation, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.Y)")); Storyboard.SetTarget(_nextAnimation, _nextItems); Storyboard.SetTargetProperty(_nextAnimation, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.Y)")); _rolloverStoryboard.Children.Add(_currentAnimation); _rolloverStoryboard.Children.Add(_nextAnimation); this.Clip = new RectangleGeometry(new Rect(new Point(), new Size(this.ActualWidth, this.ActualHeight))); } base.OnRenderSizeChanged(sizeInfo); } } }