using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media.Animation; namespace HMI.UI { public class ScrollLabel : Control { static ScrollLabel() { DefaultStyleKeyProperty.OverrideMetadata(typeof(ScrollLabel), new FrameworkPropertyMetadata(typeof(ScrollLabel))); } private DoubleAnimation animation; public override void OnApplyTemplate() { base.OnApplyTemplate(); // 在模板应用后启动初始动画 var scrollViewer = GetTemplateChild("slv") as ScrollViewer; var label = GetTemplateChild("label") as Label; if (scrollViewer != null) { // 等待布局完成后再启动动画 scrollViewer.Loaded += (s, e) => { var storyboard = new Storyboard(); animation = new DoubleAnimation { From = 0, To = scrollViewer.ScrollableWidth, Duration = new Duration(TimeSpan.FromSeconds(3)), AutoReverse = true, RepeatBehavior = RepeatBehavior.Forever, BeginTime = TimeSpan.FromSeconds(0.2) }; Storyboard.SetTarget(animation, scrollViewer); Storyboard.SetTargetProperty(animation, new PropertyPath(ScrollViewerBehavior.HorizontalOffsetProperty)); storyboard.Children.Add(animation); scrollViewer.Resources["ScrollAnimation"] = storyboard; storyboard.Begin(); }; } } private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e) { //RefreshAnimation(); } private void RefreshAnimation() { // 查找ScrollViewer并重新启动动画 var scrollViewer = GetTemplateChild("slv") as ScrollViewer; if (scrollViewer != null) { scrollViewer.Dispatcher.BeginInvoke(new Action(() => { // 停止当前动画 var storyboard = scrollViewer.Resources["ScrollAnimation"] as Storyboard; if (storyboard != null) { storyboard.Stop(); if (animation != null) { animation.To = scrollViewer.ScrollableWidth; } storyboard.Begin(); } }), System.Windows.Threading.DispatcherPriority.Background); } } public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached("Value", typeof(string), typeof(ScrollLabel), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnValueChanged))); private static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { var scrollLabel = obj as ScrollLabel; scrollLabel?.RefreshAnimation(); } public event EventHandler ValueChanged; public string Value { get { return (string)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } } } public static class ScrollViewerBehavior { public static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.RegisterAttached("HorizontalOffset", typeof(double), typeof(ScrollViewerBehavior), new UIPropertyMetadata(0.0, OnHorizontalOffsetChanged)); public static void SetHorizontalOffset(FrameworkElement target, double value) { target.SetValue(HorizontalOffsetProperty, value); } public static double GetHorizontalOffset(FrameworkElement target) { return (double)target.GetValue(HorizontalOffsetProperty); } private static void OnHorizontalOffsetChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) { var view = target as ScrollViewer; if (view != null) { view.ScrollToHorizontalOffset((double)e.NewValue); } } public static readonly DependencyProperty VerticalOffsetProperty = DependencyProperty.RegisterAttached("VerticalOffset", typeof(double), typeof(ScrollViewerBehavior), new UIPropertyMetadata(0.0, OnVerticalOffsetChanged)); public static void SetVerticalOffset(FrameworkElement target, double value) { target.SetValue(VerticalOffsetProperty, value); } public static double GetVerticalOffset(FrameworkElement target) { return (double)target.GetValue(VerticalOffsetProperty); } private static void OnVerticalOffsetChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) { var view = target as ScrollViewer; if (view != null) { view.ScrollToVerticalOffset((double)e.NewValue); } } } }