@@ -26,7 +26,7 @@ public static partial class ListViewExtensions
2626 /// <param name="scrollIfVisible">Set false to disable scrolling when the corresponding item is in view</param>
2727 /// <param name="additionalHorizontalOffset">Adds additional horizontal offset</param>
2828 /// <param name="additionalVerticalOffset">Adds additional vertical offset</param>
29- /// <returns>Note: Even though this return <see cref="Task"/>, it will not wait until the scrolling completes </returns>
29+ /// <returns>Returns <see cref="Task"/> that completes after scrolling</returns>
3030 public static async Task SmoothScrollIntoViewWithIndexAsync ( this ListViewBase listViewBase , int index , ScrollItemPlacement itemPlacement = ScrollItemPlacement . Default , bool disableAnimation = false , bool scrollIfVisible = true , int additionalHorizontalOffset = 0 , int additionalVerticalOffset = 0 )
3131 {
3232 if ( index > ( listViewBase . Items . Count - 1 ) )
@@ -56,15 +56,15 @@ public static async Task SmoothScrollIntoViewWithIndexAsync(this ListViewBase li
5656 previousXOffset = scrollViewer . HorizontalOffset ;
5757 previousYOffset = scrollViewer . VerticalOffset ;
5858
59- var tcs = new TaskCompletionSource < object > ( ) ;
59+ var tcs = new TaskCompletionSource < VoidResult > ( ) ;
6060
61- void ViewChanged ( object obj , ScrollViewerViewChangedEventArgs args ) => tcs . TrySetResult ( result : null ) ;
61+ void ViewChanged ( object obj , ScrollViewerViewChangedEventArgs args ) => tcs . TrySetResult ( result : default ) ;
6262
6363 try
6464 {
6565 scrollViewer . ViewChanged += ViewChanged ;
6666 listViewBase . ScrollIntoView ( listViewBase . Items [ index ] , ScrollIntoViewAlignment . Leading ) ;
67- await tcs . Task ;
67+ await tcs . Task . ConfigureAwait ( true ) ;
6868 }
6969 finally
7070 {
@@ -80,20 +80,7 @@ public static async Task SmoothScrollIntoViewWithIndexAsync(this ListViewBase li
8080 // Scrolling back to previous position
8181 if ( isVirtualizing )
8282 {
83- var tcs = new TaskCompletionSource < object > ( ) ;
84-
85- void ViewChanged ( object obj , ScrollViewerViewChangedEventArgs args ) => tcs . TrySetResult ( result : null ) ;
86-
87- try
88- {
89- scrollViewer . ViewChanged += ViewChanged ;
90- scrollViewer . ChangeView ( previousXOffset , previousYOffset , zoomFactor : null , disableAnimation : true ) ;
91- await tcs . Task ;
92- }
93- finally
94- {
95- scrollViewer . ViewChanged -= ViewChanged ;
96- }
83+ await scrollViewer . ChangeViewAsync ( previousXOffset , previousYOffset , zoomFactor : null , disableAnimation : true ) . ConfigureAwait ( true ) ;
9784 }
9885
9986 var listViewBaseWidth = listViewBase . ActualWidth ;
@@ -185,7 +172,7 @@ public static async Task SmoothScrollIntoViewWithIndexAsync(this ListViewBase li
185172 }
186173 }
187174
188- scrollViewer . ChangeView ( finalXPosition , finalYPosition , zoomFactor : null , disableAnimation ) ;
175+ await scrollViewer . ChangeViewAsync ( finalXPosition , finalYPosition , zoomFactor : null , disableAnimation ) . ConfigureAwait ( true ) ;
189176 }
190177
191178 /// <summary>
@@ -198,10 +185,42 @@ public static async Task SmoothScrollIntoViewWithIndexAsync(this ListViewBase li
198185 /// <param name="scrollIfVisibile">Set true to disable scrolling when the corresponding item is in view</param>
199186 /// <param name="additionalHorizontalOffset">Adds additional horizontal offset</param>
200187 /// <param name="additionalVerticalOffset">Adds additional vertical offset</param>
201- /// <returns>Note: Even though this return <see cref="Task"/>, it will not wait until the scrolling completes </returns>
188+ /// <returns>Returns <see cref="Task"/> that completes after scrolling</returns>
202189 public static async Task SmoothScrollIntoViewWithItemAsync ( this ListViewBase listViewBase , object item , ScrollItemPlacement itemPlacement = ScrollItemPlacement . Default , bool disableAnimation = false , bool scrollIfVisibile = true , int additionalHorizontalOffset = 0 , int additionalVerticalOffset = 0 )
203190 {
204- await SmoothScrollIntoViewWithIndexAsync ( listViewBase , listViewBase . Items . IndexOf ( item ) , itemPlacement , disableAnimation , scrollIfVisibile , additionalHorizontalOffset , additionalVerticalOffset ) ;
191+ await SmoothScrollIntoViewWithIndexAsync ( listViewBase , listViewBase . Items . IndexOf ( item ) , itemPlacement , disableAnimation , scrollIfVisibile , additionalHorizontalOffset , additionalVerticalOffset ) . ConfigureAwait ( true ) ;
192+ }
193+
194+ /// <summary>
195+ /// Changes the view of <see cref="ScrollViewer"/> asynchronous.
196+ /// </summary>
197+ /// <param name="scrollViewer">The scroll viewer.</param>
198+ /// <param name="horizontalOffset">The horizontal offset.</param>
199+ /// <param name="verticalOffset">The vertical offset.</param>
200+ /// <param name="zoomFactor">The zoom factor.</param>
201+ /// <param name="disableAnimation">if set to <c>true</c> disable animation.</param>
202+ private static async Task ChangeViewAsync ( this ScrollViewer scrollViewer , double ? horizontalOffset , double ? verticalOffset , float ? zoomFactor , bool disableAnimation )
203+ {
204+ var tcs = new TaskCompletionSource < VoidResult > ( ) ;
205+
206+ void ViewChanged ( object _ , ScrollViewerViewChangedEventArgs __ ) => tcs . TrySetResult ( result : default ) ;
207+
208+ try
209+ {
210+ scrollViewer . ViewChanged += ViewChanged ;
211+ scrollViewer . ChangeView ( horizontalOffset , verticalOffset , zoomFactor , disableAnimation ) ;
212+ await tcs . Task . ConfigureAwait ( true ) ;
213+ }
214+ finally
215+ {
216+ scrollViewer . ViewChanged -= ViewChanged ;
217+ }
205218 }
219+
220+ /// <summary>
221+ /// Used as a placeholder TResult to indicate that a <![CDATA[Task<TResult>]]> has a void TResult
222+ /// </summary>
223+ /// <see href="https://referencesource.microsoft.com/#System.Core/System/Threading/Tasks/TaskExtensions.cs,6e36a68760fb02e6,references"/>
224+ private struct VoidResult { }
206225 }
207226}
0 commit comments