11using System . Diagnostics ;
2+ using System . Windows . Media . Animation ;
23using Microsoft . Xaml . Behaviors ;
34
45namespace MaterialDesignThemes . Wpf . Behaviors . Internal ;
56
67public class TabControlHeaderScrollBehavior : Behavior < ScrollViewer >
78{
9+ public static readonly DependencyProperty CustomHorizontalOffsetProperty =
10+ DependencyProperty . RegisterAttached ( "CustomHorizontalOffset" , typeof ( double ) ,
11+ typeof ( TabControlHeaderScrollBehavior ) , new PropertyMetadata ( 0d , CustomHorizontalOffsetChanged ) ) ;
12+ public static double GetCustomHorizontalOffset ( DependencyObject obj ) => ( double ) obj . GetValue ( CustomHorizontalOffsetProperty ) ;
13+ public static void SetCustomHorizontalOffset ( DependencyObject obj , double value ) => obj . SetValue ( CustomHorizontalOffsetProperty , value ) ;
14+ private static void CustomHorizontalOffsetChanged ( DependencyObject d , DependencyPropertyChangedEventArgs e )
15+ {
16+ var scrollViewer = ( ScrollViewer ) d ;
17+ scrollViewer . ScrollToHorizontalOffset ( ( double ) e . NewValue ) ;
18+ }
19+
820 public static readonly DependencyProperty TabScrollDirectionProperty =
9- DependencyProperty . RegisterAttached ( "TabScrollDirection" , typeof ( TabScrollDirection ) , typeof ( TabControlHeaderScrollBehavior ) , new PropertyMetadata ( TabScrollDirection . Unknown ) ) ;
21+ DependencyProperty . RegisterAttached ( "TabScrollDirection" , typeof ( TabScrollDirection ) ,
22+ typeof ( TabControlHeaderScrollBehavior ) , new PropertyMetadata ( TabScrollDirection . Unknown ) ) ;
1023 public static TabScrollDirection GetTabScrollDirection ( DependencyObject obj ) => ( TabScrollDirection ) obj . GetValue ( TabScrollDirectionProperty ) ;
1124 public static void SetTabScrollDirection ( DependencyObject obj , TabScrollDirection value ) => obj . SetValue ( TabScrollDirectionProperty , value ) ;
1225
@@ -33,12 +46,16 @@ private static void OnTabControlChanged(DependencyObject d, DependencyPropertyCh
3346 }
3447 }
3548
49+ private double ? _desiredScrollStart ;
50+ private bool _isAnimatingScroll ;
51+
3652 private void OnTabChanged ( object sender , SelectionChangedEventArgs e )
3753 {
3854 TabControl tabControl = ( TabControl ) sender ;
3955
4056 if ( e . AddedItems . Count > 0 )
4157 {
58+ _desiredScrollStart = AssociatedObject . ContentHorizontalOffset ;
4259 SetTabScrollDirection ( tabControl , ( IsMovingForward ( ) ? TabScrollDirection . Forward : TabScrollDirection . Backward ) ) ;
4360 }
4461
@@ -70,7 +87,23 @@ protected override void OnDetaching()
7087
7188 private void AssociatedObject_ScrollChanged ( object sender , ScrollChangedEventArgs e )
7289 {
73- Debug . WriteLine ( $ "HorizontalOffset: { e . HorizontalOffset } , ViewportWidth: { e . ViewportWidth } , ExtentWidth: { e . ExtentWidth } ") ;
90+ Debug . WriteLine ( $ "ContentHorizontalOffset: { AssociatedObject . ContentHorizontalOffset } , HorizontalOffset: { e . HorizontalOffset } , HorizontalChange: { e . HorizontalChange } , ViewportWidth: { e . ViewportWidth } , ExtentWidth: { e . ExtentWidth } ") ;
91+ if ( _isAnimatingScroll || _desiredScrollStart is not { } desiredOffsetStart ) return ;
92+
93+ double originalValue = desiredOffsetStart ;
94+ double newValue = e . HorizontalOffset ;
95+
96+ _isAnimatingScroll = true ;
97+ AssociatedObject . ScrollToHorizontalOffset ( originalValue ) ;
98+ Debug . WriteLine ( $ "Initiating animated scroll from { originalValue } to { newValue } . Change is: { e . HorizontalChange } ") ;
99+ DoubleAnimation scrollAnimation = new ( originalValue , newValue , new Duration ( TimeSpan . FromMilliseconds ( 250 ) ) ) ;
100+ scrollAnimation . Completed += ( _ , _ ) =>
101+ {
102+ Debug . WriteLine ( "Animation completed" ) ;
103+ _desiredScrollStart = null ;
104+ _isAnimatingScroll = false ;
105+ } ;
106+ AssociatedObject . BeginAnimation ( TabControlHeaderScrollBehavior . CustomHorizontalOffsetProperty , scrollAnimation ) ;
74107 }
75108}
76109
0 commit comments