alielie
2026-06-15 f08871fe7d148d667f2f11f80f64de71a0d9504c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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<string> 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);
            }
        }
    }
 
}