-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Changed SmoothScrollIntoView method to be truly asynchronous #4129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changed SmoothScrollIntoView method to be truly asynchronous #4129
Conversation
Thanks Vijay-Nirmal for opening a Pull Request! The reviewers will test the PR and highlight if there is any conflict or changes required. If the PR is approved we will proceed to merge the pull request 🙌 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested this with showing a dialog message after invoking the smooth scrolling in the sample, and it seemed that the task did not wait for the animation to complete. Is this the intended behavior?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested this with showing a dialog message after invoking the smooth scrolling in the sample, and it seemed that the task did not wait for the animation to complete. Is this the intended behavior?
Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ListViewExtensions/ListViewExtensionsPage.xaml.cs
Outdated
Show resolved
Hide resolved
Microsoft.Toolkit.Uwp.UI/Extensions/ListViewBase/ListViewExtensions.SmoothScrollIntoView.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Rosario Pulella <[email protected]>
@RosarioPulella Fixed the issue. Please re-review it. Again, thanks for testing in the first place :) |
/// <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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The 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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The 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 ChangeView
can take longer to return? (Like if that's the case, we should probably call that out in the method doc comment so folks know when to use this over the built-in one.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the idea is if you have animation the original ChangeView can take longer to return?
I am not sure what you mean exactly. If we have animation in the original ChangeView
then it will act as fire and forget not as a synchronous call. There is no built-in way to asynchronously wait until the animation completes. ChangeViewAsync
methods does that, it can asynchronously wait until the animation completes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The 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.
Happy to help @Vijay-Nirmal C: , thanks for contributing! Also I wonder if its worth changing the sample to include an option to show a message when the scrolling finishes? (Like my experiment) |
private struct VoidResult | ||
{ | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This type is unnecessary here, and it's also causing a non-shared generic instantiation of TaskCompletionSource<T>
to be created. The previous usage of TaskCompletionSource<object>
was completely fine and I don't really see a reason to change it. Besides, in the .NET 5 branch for the WinUI 3 target that'll just be moved to TaskCompletionSource
(non generic) as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This type is unnecessary here
Agree. This will just prevent 4 bytes allocation in heap, that's all. I know it will be negotiable. I will remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I'm following, I don't really see how this change is avoiding any heap allocations.
Also where is that 4 bytes number coming from? Even on a 32 bit system, every allocated object would always have a size of at least 8 bytes due to the space for the object header and method table pointer. Can you elaborate? 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Sergio0694 Sorry about the memory allocations, got confused with the generic implementation.
The below comment is from docs.microsoft.com
The TaskCompletionSource class doesn't have a non-generic counterpart........ (Boolean is a good default choice, but if you're concerned about the user of the Task downcasting it to a Task, you can use a private TResult type instead).
I understand this is overkill 🤣, just need to point this out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That but you quoted from the docs is outdated, there is a non-generic TaskCompletionSource
type from .NET 5. As for your other point, I don't think we should be concerned about consumers potentially down casting to that generic task type and doing...? I don't think that'd be an issue either way, and besides we'll move to the non-generic type in the WinUI branch anyway (which has .NET 5), so this is all just temporary 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know its outdated, I have raised an issue in their repo to fix the doc issue 😉. Just had a chance to point it out before fixing 😁
|
||
try | ||
{ | ||
scrollViewer.ViewChanged += ViewChanged; | ||
listViewBase.ScrollIntoView(listViewBase.Items[index], ScrollIntoViewAlignment.Leading); | ||
await tcs.Task; | ||
await tcs.Task.ConfigureAwait(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All these ConfigureAwait(true)
calls don't actually do anything and they just create more noise, we should remove them. ConfigureAwait(bool)
should really only ever be used with false
, and the only reason it takes a parameter is because it might possibly be useful in some niche test scenarios where you might want to control that behavior at runtime. But ConfigureAwait(true)
on its own is just meaningless.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will remove it.
My thought process: In this case, ConfigureAwait
must be true
otherwise my code will break. Somewhere in the guidelines or in an official blog, I saw that we should specify ConfigureAwait
as true
if we are purposefully not using ConfigureAwait(false)
. Anyway, I will remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The 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.
See this blog post from Stephen Toub 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The 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.
You wouldn’t, unless you were using it purely as an indication that you were purposefully not using ConfigureAwait(false)
But I agree with you, personally, I also don't like it. Just trying to follow standards while raising a PR for Microsoft itself. 😁
This PR has been marked as "needs attention 👋" and awaiting a response from the team. |
@RosarioPulella Sure, I will add it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love the indicator! I just think that verbiage can be clearer and more accurate.
Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ListViewExtensions/ListViewExtensionsPage.xaml
Outdated
Show resolved
Hide resolved
Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ListViewExtensions/ListViewExtensionsPage.xaml.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Rosario Pulella <[email protected]>
Co-authored-by: Rosario Pulella <[email protected]>
It seems making the sample show the behavior of the control more clearly has helped reveal an issue. If add a horizontally offset and scroll, the indicator changes to scrolling and never changes back. I put brake points to confirm that the task never completes. Also I am seeing another behavior with the offsets. If I set a vertical offset and scroll, it seems to move to a position relative to its current position and not the set index. This means if I set a vertical offset to 15 it will move every time I click scroll, even if I did not change any values afterwords. Is this the intended behavior? |
Yes, my bad. I know why this issue exists. I will fix it.
I believe this will happen when item placement is Currently, I will say "No" it's not the intended behavior and write a special case for this situation. @RosarioPulella What's your opinion? |
I have a few thoughts, but maybe we should open an issue and discuss there, to keep this PR focused. I wanted to make sure this behavior was not introduced in this PR. It was my oversight to not discuss this part of the behavior more in the original PR. |
Fixed this issue.
@RosarioPulella I will open an issue to discuss this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good now! Thanks @Vijay-Nirmal!
@Sergio0694 you good now too? |
Hello @michael-hawker! Because this pull request has the p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (
|
@msftbot merge once @Sergio0694 approves. |
Hello @michael-hawker! Because you've given me some instructions on how to help merge this pull request, I'll be modifying my merge approach. Here's how I understand your requirements for merging this pull request:
If this doesn't seem right to you, you can tell me to cancel these instructions and use the auto-merge policy that has been configured for this repository. Try telling me "forget everything I just told you". |
Fixes #4128
PR Type
What kind of change does this PR introduce?
What is the current behavior?
Currently,
SmoothScrollIntoViewWithIndexAsync
is not truly asynchronous but it will return aTask
.What is the new behavior?
SmoothScrollIntoView method should be truly asynchronous. It should wait until the animation completes
PR Checklist
Please check if your PR fulfills the following requirements:
Other information
I have not tested this since I am encountering an issue while building the application locally. Below is the issue I am facing while building (It's not related to this code change)I will try to solve this issue. In meantime, can anyone test this PR if possible? sorry for this inconvenience