@@ -37,7 +37,7 @@ public static bool IsSmoothScrolling(this ScrollViewer scrollViewer) =>
3737 /// <param name="visual"><see cref="Visual"/> inside <see cref="ScrollViewer"/>.</param>
3838 /// <returns>True if visual has been scrolled into view.</returns>
3939 public static bool ScrollIntoView ( this ScrollViewer scrollViewer , Visual visual ) =>
40- ScrollIntoView ( scrollViewer , visual , TimeSpan . Zero , null , false ) ;
40+ ScrollIntoView ( scrollViewer , visual , TimeSpan . Zero , null , false , null , null ) ;
4141
4242
4343 /// <summary>
@@ -48,11 +48,11 @@ public static bool ScrollIntoView(this ScrollViewer scrollViewer, Visual visual)
4848 /// <param name="scrollToCenter">True to try scrolling <see cref="Visual"/> to center of viewport.</param>
4949 /// <returns>True if visual has been scrolled into view.</returns>
5050 public static bool ScrollIntoView ( this ScrollViewer scrollViewer , Visual visual , bool scrollToCenter ) =>
51- ScrollIntoView ( scrollViewer , visual , TimeSpan . Zero , null , scrollToCenter ) ;
51+ ScrollIntoView ( scrollViewer , visual , TimeSpan . Zero , null , scrollToCenter , null , null ) ;
5252
5353
5454 // Scroll given visual into viewport of ScrollViewer.
55- static bool ScrollIntoView ( ScrollViewer scrollViewer , Visual visual , TimeSpan duration , Func < double , double > ? interpolator , bool scrollToCenter )
55+ static bool ScrollIntoView ( ScrollViewer scrollViewer , Visual visual , TimeSpan duration , Func < double , double > ? interpolator , bool scrollToCenter , Action ? onCompleted , Action ? onCancelled )
5656 {
5757 // check parameter
5858 if ( scrollViewer == visual )
@@ -139,12 +139,12 @@ static bool ScrollIntoView(ScrollViewer scrollViewer, Visual visual, TimeSpan du
139139 } ) ;
140140
141141 // scroll to content
142- return ScrollTo ( scrollViewer , new ( newOffsetX , newOffsetY ) , duration , interpolator ) ;
142+ return ScrollTo ( scrollViewer , new ( newOffsetX , newOffsetY ) , duration , interpolator , onCompleted , onCancelled ) ;
143143 }
144144
145145
146146 // Scroll to given offset.
147- static bool ScrollTo ( ScrollViewer scrollViewer , Vector offset , TimeSpan duration , Func < double , double > ? interpolator )
147+ static bool ScrollTo ( ScrollViewer scrollViewer , Vector offset , TimeSpan duration , Func < double , double > ? interpolator , Action ? onCompleted , Action ? onCancelled )
148148 {
149149 // get top level
150150 if ( TopLevel . GetTopLevel ( scrollViewer ) is not { } topLevel )
@@ -187,6 +187,7 @@ void OnPointerWheelChanged(object? sender, RoutedEventArgs e) =>
187187 scrollViewer . RemoveHandler ( InputElement . PointerPressedEvent , OnPointerPressed ) ;
188188 scrollViewer . RemoveHandler ( InputElement . PointerWheelChangedEvent , OnPointerWheelChanged ) ;
189189 viewportChangedObserverToken . Dispose ( ) ;
190+ onCancelled ? . Invoke ( ) ;
190191 } ;
191192 it . Completed += ( _ , _ ) =>
192193 {
@@ -199,6 +200,7 @@ void OnPointerWheelChanged(object? sender, RoutedEventArgs e) =>
199200 scrollViewer . RemoveHandler ( InputElement . PointerPressedEvent , OnPointerPressed ) ;
200201 scrollViewer . RemoveHandler ( InputElement . PointerWheelChangedEvent , OnPointerWheelChanged ) ;
201202 viewportChangedObserverToken . Dispose ( ) ;
203+ onCompleted ? . Invoke ( ) ;
202204 } ;
203205 it . Duration = duration ;
204206 it . Interpolator = interpolator ?? Interpolators . Default ;
@@ -211,7 +213,10 @@ void OnPointerWheelChanged(object? sender, RoutedEventArgs e) =>
211213 animator . Start ( ) ;
212214 }
213215 else
216+ {
214217 scrollViewer . Offset = new ( offsetX , offsetY ) ;
218+ onCompleted ? . Invoke ( ) ;
219+ }
215220 return true ;
216221 }
217222
@@ -225,8 +230,24 @@ void OnPointerWheelChanged(object? sender, RoutedEventArgs e) =>
225230 /// <param name="interpolator">Interpolator of smooth scrolling.</param>
226231 /// <param name="scrollToCenter">True to scroll content to center of viewport.</param>
227232 /// <returns>True if smooth scrolling starts successfully.</returns>
228- public static bool SmoothScrollIntoView ( this ScrollViewer scrollViewer , Visual visual , TimeSpan duration , Func < double , double > ? interpolator = null , bool scrollToCenter = true ) =>
229- ScrollIntoView ( scrollViewer , visual , duration , interpolator , scrollToCenter ) ;
233+ public static bool SmoothScrollIntoView ( this ScrollViewer scrollViewer , Visual visual , TimeSpan duration , Func < double , double > ? interpolator , bool scrollToCenter ) =>
234+ ScrollIntoView ( scrollViewer , visual , duration , interpolator , scrollToCenter , null , null ) ;
235+
236+
237+ /// <summary>
238+ /// Scroll given <see cref="Visual"/> smoothly into viewport of <see cref="ScrollViewer"/>.
239+ /// </summary>
240+ /// <param name="scrollViewer"><see cref="ScrollViewer"/>.</param>
241+ /// <param name="visual"><see cref="Visual"/>.</param>
242+ /// <param name="duration">Duration of smooth scrolling.</param>
243+ /// <param name="interpolator">Interpolator of smooth scrolling.</param>
244+ /// <param name="scrollToCenter">True to scroll content to center of viewport.</param>
245+ /// <param name="onCompleted">Function to be called when scrolling completed.</param>
246+ /// <param name="onCancelled">Function to be called when scrolling cancelled.</param>
247+ /// <returns>True if smooth scrolling starts successfully.</returns>
248+ // ReSharper disable once MethodOverloadWithOptionalParameter
249+ public static bool SmoothScrollIntoView ( this ScrollViewer scrollViewer , Visual visual , TimeSpan duration , Func < double , double > ? interpolator = null , bool scrollToCenter = true , Action ? onCompleted = null , Action ? onCancelled = null ) =>
250+ ScrollIntoView ( scrollViewer , visual , duration , interpolator , scrollToCenter , onCompleted , onCancelled ) ;
230251
231252
232253 /// <summary>
@@ -237,8 +258,23 @@ public static bool SmoothScrollIntoView(this ScrollViewer scrollViewer, Visual v
237258 /// <param name="duration">Duration of smooth scrolling.</param>
238259 /// <param name="interpolator">Interpolator of smooth scrolling.</param>
239260 /// <returns>True if smooth scrolling starts successfully.</returns>
240- public static bool SmoothScrollTo ( this ScrollViewer scrollViewer , Vector offset , TimeSpan duration , Func < double , double > ? interpolator = null ) =>
241- ScrollTo ( scrollViewer , offset , duration , interpolator ) ;
261+ public static bool SmoothScrollTo ( this ScrollViewer scrollViewer , Vector offset , TimeSpan duration , Func < double , double > ? interpolator ) =>
262+ ScrollTo ( scrollViewer , offset , duration , interpolator , null , null ) ;
263+
264+
265+ /// <summary>
266+ /// Scroll <see cref="ScrollViewer"/> to given offset smoothly.
267+ /// </summary>
268+ /// <param name="scrollViewer"><see cref="ScrollViewer"/>.</param>
269+ /// <param name="offset">Target offset.</param>
270+ /// <param name="duration">Duration of smooth scrolling.</param>
271+ /// <param name="interpolator">Interpolator of smooth scrolling.</param>
272+ /// <param name="onCompleted">Function to be called when scrolling completed.</param>
273+ /// <param name="onCancelled">Function to be called when scrolling cancelled.</param>
274+ /// <returns>True if smooth scrolling starts successfully.</returns>
275+ // ReSharper disable once MethodOverloadWithOptionalParameter
276+ public static bool SmoothScrollTo ( this ScrollViewer scrollViewer , Vector offset , TimeSpan duration , Func < double , double > ? interpolator = null , Action ? onCompleted = null , Action ? onCancelled = null ) =>
277+ ScrollTo ( scrollViewer , offset , duration , interpolator , onCompleted , onCancelled ) ;
242278
243279
244280 /// <summary>
0 commit comments