dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.23k stars 1.76k forks source link

ScrollView.ScrollToAsync not working if Children.Add used in the same method #10283

Open Tardigrade42 opened 2 years ago

Tardigrade42 commented 2 years ago

Description

The ScrollToAsync method is not working, if the Children of the content are changed in the same method. For a better understanding of the issue, please see the following code:

MainPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ScrollViewScrollingIssue.app.MainPage">
    <Grid BackgroundColor="Wheat">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <ScrollView x:Name="mainScrollView"
                    Grid.Row="1"
                    VerticalScrollBarVisibility="Always">
            <StackLayout x:Name="scrollViewContent"
                     Orientation="Vertical" />
        </ScrollView>

        <Grid Grid.Row="2"
              BackgroundColor="Blue">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>

            <Button Grid.Column="0"
                    Text="Add and scroll"
                    BackgroundColor="Gray"
                    Clicked="AddAndScrollButtonListener"/>

            <Button Grid.Column="1"
                    Text="Scroll to bottom"
                    BackgroundColor="Gray"
                    Clicked="ScrollButtonListener" />

            <Label x:Name="showButtonAction"
                   Grid.Column="3"
                   VerticalOptions="Center"/>
        </Grid>
    </Grid>

</ContentPage>

MainPage.xaml.cs

using System.Diagnostics;

namespace ScrollViewScrollingIssue.app;

public partial class MainPage : ContentPage {
    public MainPage() {
        InitializeComponent();

        for (int i = 0; i < 30; i++) {
            scrollViewContent.Children.Add(
                new Label {
                    Text = "Label number " + i,
                    FontSize = 30,
                });
        }
    }

    private void ScrollButtonListener(object sender, EventArgs e) {
        ScrollDown();
    }

    private void AddAndScrollButtonListener(object sender, EventArgs e) {
        scrollViewContent.Children.Add(
                new Label {
                    Text = "Label number " + scrollViewContent.Children.Count,
                    FontSize = 30,
                });

        ScrollDown();
    }

    private async void ScrollDown() {
        int lastChild = scrollViewContent.Children.Count - 1;

        Debug.WriteLine("The last child's index is: " + lastChild);

        if (lastChild >= 0) {
            View lastElement = (View)scrollViewContent.Children[lastChild];

            Debug.WriteLine("The last child's text is: " + ((Label)lastElement).Text);

            await mainScrollView.ScrollToAsync(lastElement, ScrollToPosition.MakeVisible, false);

            showButtonAction.Text = "Scrolled to: Lable number " + lastChild + " ";
            Debug.WriteLine("Scrolled to: Lable number " + lastChild + " ");
        }
    }
}

If only the ScrollButtonListener method is called, the scroll down works just fine. But if the AddAndScrollButtonListener is called, it doesn't work. I could only test Android and Windows, and I got different - but both wrong - behaviours:

Android

When clicking the Add and scroll button, the scroll down does not work, but the ScrollToAsync method exited without doing its job. This can be seen, because the Label was updated.

Windows

When clicking the Add and scroll button, the scroll down does not work. For some reason, the ScrollToAsync does not exit. It keeps “working” until I manually scroll down. If I do so, the method is exiting.

Steps to Reproduce

  1. Clone the repo
  2. Run the App on Windows and Android
  3. If you press the Scroll to bottom button, it scrolls down like it should
  4. If you press the Add and scroll button, it adds the children but does not scroll down
  5. If you hit again the Scroll to bottom button, it scrolls down again

Link to public reproduction project repository

https://github.com/Tardigrade42/MauiIssue-ScrollViewScrollingIssue

Version with bug

6.0.486 (current)

Last version that worked well

Unknown/Other

Affected platforms

Android, Windows

Affected platform versions

Tested on Android 10.0 and Windows 10 Pro 21H2

Did you find any workaround?

No response

Relevant log output

No response

ghost commented 2 years ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

valimaties commented 2 years ago

A lot of important issues are moved to the Backlog and nothing happens. I am very dissapointed about this MAUI, I lost a month to move my WPF application to MAUI to be able to use it on Mac as well, but now I found that a lot of unsolved issues I'm facing it, and for that I'm very dissapointed. I think it must take some years to be able to use MAUI, as long as it has a lot of issues, bugs and missing things. 😒

Tardigrade42 commented 1 year ago

Hi, I have written the issue more than two months ago and have not received any feedback yet. Is there a workaround or a fix found yet?

borrmann commented 1 year ago

I am facing the same problem. In my case it is a problem when a page loads content dynamically and needs to scroll to the end after adding content.

This is my workaround in my page.cs file, where I access a viewmodel that loads data from database and updates data from backend:

private EventHandler LoadingCompleted;

protected async override void OnNavigatedTo(NavigatedToEventArgs args)
        {
            LoadingCompleted += ScrollToEndWhenPageLoaded;
            await _viewModel.LoadDataAsync();

            (scrollView as IView).InvalidateMeasure(); 
            await scrollView.ScrollToAsync(end, animated: false, position: ScrollToPosition.MakeVisible); // this does not work

            LoadingCompleted?.Invoke(this, EventArgs.Empty);
        }

        protected override void OnNavigatedFrom(NavigatedFromEventArgs args)
        {
            LoadingCompleted -= ScrollToEndWhenPageLoaded;
        }

        private async void ScrollToEndWhenPageLoaded(object sender, EventArgs e)
        {
            await Task.Delay(50);
            (scrollView as IView).InvalidateMeasure(); // this is a bug workaround on iOS
            await scrollView.ScrollToAsync(end, animated: false, position: ScrollToPosition.MakeVisible); // this works

            //MainThread.BeginInvokeOnMainThread(async () =>
            //{ if it doesnt work maybe try to ensure its on main UI thread

            //});
        }

where LB_end is the item I am scrolling to and scrollView is my ScrollView

homeyf commented 1 year ago

Verified this issue with Visual Studio Enterprise 17.7.0 Preview 2.0. Can repro on windows platform with sample project. https://github.com/Tardigrade42/MauiIssue-ScrollViewScrollingIssue demo2