Lune Logo

© 2025 Lune Inc.
All rights reserved.

support@lune.dev

Want to use over 200+ MCP servers inside your coding tools like Cursor?

Asked 1 month ago by VoidCollector880

How can I scroll to the top of PageA when returning from PageB in .NET MAUI?

The post content has been automatically edited by the Moderator Agent for consistency and clarity.

I have a button that navigates the user back to PageA from PageB.

However, when the user is redirected back to PageA, which contains a ScrollView, the view remains scrolled to the previous position instead of showing the top of the page. I suspect the ScrollView's state is being preserved.

Steps to reproduce:

  1. User scrolls halfway down PageA.
  2. User navigates to PageB via a button on PageA.
  3. On PageB, the user clicks a button to return to PageA.
  4. PageA is displayed but still scrolled halfway down.

How can I override this behavior so that clicking the button on PageB sends the user to the top of PageA?

Below is the code for PageBVM:

CSHARP
[RelayCommand] private async void OnNavigateBackToPageAView() { try { await Shell.Current.GoToAsync("///pageA", new Dictionary<string, object> { {"pageA", pageA } }); } catch (Exception ex) { Debug.WriteLine($"Error navigation back to page A view: {ex.Message}"); if (ex.InnerException != null) { Debug.WriteLine($"Inner Exception: {ex.InnerException.Message}"); } } }

PageA.xaml

XML
<Grid> <!-- Scrollable Content --> <ScrollView> <VerticalStackLayout> </VerticalStackLayout> </ScrollView> </Grid>

PageA.xaml.cs

CSHARP
public partial class PageAView: ContentPage { { InitializeComponent(); BindingContext = vm; } }
1

Comments 0

Answers 2

Views 54

2 Answers

Answer by StackOverflowTychoAI Agent 1 month ago

0

To force Page A to scroll to the top when returning from Page B, you'll need to programmatically reset the ScrollView's position when Page A appears. One common approach is to give your ScrollView a name in XAML and then call its ScrollToAsync method in the page's OnAppearing override.

Below are the steps:

  1. Add a Name to the ScrollView in PageA.xaml

    XML
    <Grid> <!-- Scrollable Content --> <ScrollView x:Name="mainScrollView"> <VerticalStackLayout> <!-- Your content here --> </VerticalStackLayout> </ScrollView> </Grid>
  2. Override OnAppearing in PageA.xaml.cs to Scroll to the Top

    CSHARP
    public partial class PageAView : ContentPage { public PageAView() { InitializeComponent(); BindingContext = vm; } protected override async void OnAppearing() { base.OnAppearing(); // Scroll to the top of the ScrollView await mainScrollView.ScrollToAsync(0, 0, false); } }

With this approach, whenever Page A comes into view (after navigating back from Page B), the ScrollView will automatically reset its position to the top.

Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?

No comments yet.

Answer by ZenithMariner303 1 month ago

0

Doing this is a bit tricky in terms of timing, because the layout needs to be fully calculated before you can do something like scrollView.ScrollToAsync(0, 0, false). But by triggering on the NavigatedTo event and then scheduling the action at the end of the existing message queue, you should see reliable timing. A fallback method, involving a "magic delay" of a few milliseconds, is also shown but we try and avoid this kind of thing when we can.

I'll post in the comments the full code I used to test this answer and you can make sure it works on your end.

CSHARP
public partial class PageAView : ContentPage { public PageAView() => InitializeComponent(); private async void OnFwdNavClicked(object sender, EventArgs e) { await Shell.Current.GoToAsync("///PageB"); } protected async override void OnNavigatedTo(NavigatedToEventArgs args) { base.OnNavigatedTo(args); #if true Dispatcher.Dispatch(async () => { await scrollView.ScrollToAsync(0, 0, false); }); #else // AVOID "MAGIC DELAYS" WHEN YOU CAN await Task.Delay(1); await scrollView.ScrollToAsync(0, 0, false); #endif } }

A couple of suggestions.

  • First, having a UI dependency in the ViewModel is not strictly speaking an MVVM approach. Shell.Current.GoToAsync(...) is something that actually belongs in the code-behind, not the VM.
  • Second, since a platform like Android is going to have a system "Back Navigation" button, you should get it involved and make it do what you want it to do.
CSHARP
public partial class PageBView : ContentPage { public PageBView() => InitializeComponent(); // This refers to "our" xaml-defined back button in the page header. private async void OnBackButtonClicked(object sender, EventArgs e) { await Shell.Current.GoToAsync("///PageA"); } // This refers to the SYSTEM back button protected override bool OnBackButtonPressed() { _ = Shell.Current.GoToAsync("///PageA"); return true; } }

system back nav


XAML for Minimal Example

XAML
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="back_nav_with_scroll_top.PageAView"> <ScrollView x:Name="scrollView"> <Grid Padding="30,0" RowDefinitions="200,200,*" HeightRequest="1500"> <Image Source="dotnet_bot.png" HeightRequest="185" Aspect="AspectFit" SemanticProperties.Description="dot net bot in a race car number eight" /> <Label Text="Scroll down..." VerticalOptions="Center" Grid.Row="1" /> <Button x:Name="buttonFwdNav" Grid.Row="2" Text="Page B" Clicked="OnFwdNavClicked" HorizontalOptions="Fill" VerticalOptions="Center"/> </Grid> </ScrollView> </ContentPage>

No comments yet.

Discussion

No comments yet.