-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Changed SmoothScrollIntoView method to be truly asynchronous #4129
Changes from 1 commit
4590172
6f1869e
3945999
602e98d
525bc25
b1033fb
8a5774e
4ee302d
625716b
a09e203
4b70980
70d7b0e
b6749fc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,7 +26,7 @@ public static partial class ListViewExtensions | |
| /// <param name="scrollIfVisible">Set false to disable scrolling when the corresponding item is in view</param> | ||
| /// <param name="additionalHorizontalOffset">Adds additional horizontal offset</param> | ||
| /// <param name="additionalVerticalOffset">Adds additional vertical offset</param> | ||
| /// <returns>Note: Even though this return <see cref="Task"/>, it will not wait until the scrolling completes</returns> | ||
| /// <returns>Returns <see cref="Task"/> that completes after scrolling</returns> | ||
| 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) | ||
| { | ||
| if (index > (listViewBase.Items.Count - 1)) | ||
|
|
@@ -56,15 +56,15 @@ public static async Task SmoothScrollIntoViewWithIndexAsync(this ListViewBase li | |
| previousXOffset = scrollViewer.HorizontalOffset; | ||
| previousYOffset = scrollViewer.VerticalOffset; | ||
|
|
||
| var tcs = new TaskCompletionSource<object>(); | ||
| var tcs = new TaskCompletionSource<VoidResult>(); | ||
|
|
||
| void ViewChanged(object obj, ScrollViewerViewChangedEventArgs args) => tcs.TrySetResult(result: null); | ||
| void ViewChanged(object obj, ScrollViewerViewChangedEventArgs args) => tcs.TrySetResult(result: default); | ||
|
|
||
| try | ||
| { | ||
| scrollViewer.ViewChanged += ViewChanged; | ||
| listViewBase.ScrollIntoView(listViewBase.Items[index], ScrollIntoViewAlignment.Leading); | ||
| await tcs.Task; | ||
| await tcs.Task.ConfigureAwait(true); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All these
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will remove it. My thought process: In this case,
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure where that was from, but the official guideline is to just remove it, as it doesn't do anything.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From the blog, you point out. In my case, this must be running on the same thread (UI Thread) otherwise my code will break.
But I agree with you, personally, I also don't like it. Just trying to follow standards while raising a PR for Microsoft itself. 😁 |
||
| } | ||
| finally | ||
| { | ||
|
|
@@ -80,20 +80,7 @@ public static async Task SmoothScrollIntoViewWithIndexAsync(this ListViewBase li | |
| // Scrolling back to previous position | ||
| if (isVirtualizing) | ||
| { | ||
| var tcs = new TaskCompletionSource<object>(); | ||
|
|
||
| void ViewChanged(object obj, ScrollViewerViewChangedEventArgs args) => tcs.TrySetResult(result: null); | ||
|
|
||
| try | ||
| { | ||
| scrollViewer.ViewChanged += ViewChanged; | ||
| scrollViewer.ChangeView(previousXOffset, previousYOffset, zoomFactor: null, disableAnimation: true); | ||
| await tcs.Task; | ||
| } | ||
| finally | ||
| { | ||
| scrollViewer.ViewChanged -= ViewChanged; | ||
| } | ||
| await scrollViewer.ChangeViewAsync(previousXOffset, previousYOffset, zoomFactor: null, disableAnimation: true).ConfigureAwait(true); | ||
| } | ||
|
|
||
| var listViewBaseWidth = listViewBase.ActualWidth; | ||
|
|
@@ -185,7 +172,7 @@ public static async Task SmoothScrollIntoViewWithIndexAsync(this ListViewBase li | |
| } | ||
| } | ||
|
|
||
| scrollViewer.ChangeView(finalXPosition, finalYPosition, zoomFactor: null, disableAnimation); | ||
| await scrollViewer.ChangeViewAsync(finalXPosition, finalYPosition, zoomFactor: null, disableAnimation).ConfigureAwait(true); | ||
| } | ||
|
|
||
| /// <summary> | ||
|
|
@@ -198,10 +185,42 @@ public static async Task SmoothScrollIntoViewWithIndexAsync(this ListViewBase li | |
| /// <param name="scrollIfVisibile">Set true to disable scrolling when the corresponding item is in view</param> | ||
| /// <param name="additionalHorizontalOffset">Adds additional horizontal offset</param> | ||
| /// <param name="additionalVerticalOffset">Adds additional vertical offset</param> | ||
| /// <returns>Note: Even though this return <see cref="Task"/>, it will not wait until the scrolling completes</returns> | ||
| /// <returns>Returns <see cref="Task"/> that completes after scrolling</returns> | ||
| 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) | ||
| { | ||
| await SmoothScrollIntoViewWithIndexAsync(listViewBase, listViewBase.Items.IndexOf(item), itemPlacement, disableAnimation, scrollIfVisibile, additionalHorizontalOffset, additionalVerticalOffset); | ||
| await SmoothScrollIntoViewWithIndexAsync(listViewBase, listViewBase.Items.IndexOf(item), itemPlacement, disableAnimation, scrollIfVisibile, additionalHorizontalOffset, additionalVerticalOffset).ConfigureAwait(true); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Changes the view of <see cref="ScrollViewer"/> asynchronous. | ||
| /// </summary> | ||
| /// <param name="scrollViewer">The scroll viewer.</param> | ||
| /// <param name="horizontalOffset">The horizontal offset.</param> | ||
| /// <param name="verticalOffset">The vertical offset.</param> | ||
| /// <param name="zoomFactor">The zoom factor.</param> | ||
| /// <param name="disableAnimation">if set to <c>true</c> disable animation.</param> | ||
| private static async Task ChangeViewAsync(this ScrollViewer scrollViewer, double? horizontalOffset, double? verticalOffset, float? zoomFactor, bool disableAnimation) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you guys think this method should be public? Will this extension method be useful for developers as well?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, we could expose this. I guess the idea is if you have animation the original
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I am not sure what you mean exactly. If we have animation in the original
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool, in either case, this could be helpful. @JustinXinLiu would you use something like this? Since this PR is good to go right now, we can always open a different one later, as we'd want to improve docs with an example maybe. |
||
| { | ||
| var tcs = new TaskCompletionSource<VoidResult>(); | ||
|
|
||
| void ViewChanged(object _, ScrollViewerViewChangedEventArgs __) => tcs.TrySetResult(result: default); | ||
|
|
||
| try | ||
| { | ||
| scrollViewer.ViewChanged += ViewChanged; | ||
| scrollViewer.ChangeView(horizontalOffset, verticalOffset, zoomFactor, disableAnimation); | ||
| await tcs.Task.ConfigureAwait(true); | ||
| } | ||
| finally | ||
| { | ||
| scrollViewer.ViewChanged -= ViewChanged; | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Used as a placeholder TResult to indicate that a <![CDATA[Task<TResult>]]> has a void TResult | ||
| /// </summary> | ||
| /// <see href="https://referencesource.microsoft.com/#System.Core/System/Threading/Tasks/TaskExtensions.cs,6e36a68760fb02e6,references"/> | ||
| private struct VoidResult { } | ||
|
Vijay-Nirmal marked this conversation as resolved.
Outdated
|
||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.