Correct place to call ScrollToAsync when ItemsSource changes in view model

khickskhicks USUniversity ✭✭

On my ContentPage, I use an ItemsControl (https://github.com/xamarinhq/xamu-infrastructure/blob/master/src/XamU.Infrastructure/Controls/ItemsControl.cs) to display a horizontal StackLayout of templated items bound to an ItemsSource, inside a ScrollView.

<ScrollView Orientation="Horizontal" x:Name="MyScrollView"> <userControls:ItemsControl ItemsSource="{Binding MyItems}" x:Name="MyItemsControl"> <userControls:ItemsControl.ItemTemplate> <DataTemplate> ... </DataTemplate> </userControls:ItemsControl.ItemTemplate> </userControls:ItemsControl> </ScrollView>

When I navigate to my page, my view model sets MyItems to an ObservableCollection, and the ItemsControl may exceed the screen width. When this happens, I need to scroll to the end of the ScrollView so the last elements in MyItems are visible.

I have tried overriding LayoutChildren in both the page and the ItemsControl, and while it sometimes works, it also is inconsistent and sometimes stops the scroll view part of the way through the items.

protected override async void LayoutChildren(double x, double y, double width, double height) { base.LayoutChildren(x, y, width, height); if (_previousWidth != MyItemsControl.Width) { _previousWidth = MyItemsControl.Width; if (MyItemsControl.Width > screenWidth) { //await Task.Yield(); await BreadcrumbScrollView.ScrollToAsync(_previousWidth-screenWidth, 0, false); } } }

Since LayoutChildren gets called multiple times (and varies by platform), is there any way to know when the layout is complete so that I can call ScrollToAsync once?

Answers

  • khickskhicks USUniversity ✭✭

    For now, I have performed two RotationY transformations...one on the scroll view (to reflect the scroll view over the Y-axis to make the scrolling start on the right), and one on the actual content (to get the content back to its original orientation).

    <ScrollView Orientation="Horizontal" x:Name="MyScrollView" RotationY="180" HorizontalOptions="Start"> <userControls:ItemsControl ItemsSource="{Binding MyItems}" x:Name="MyItemsControl" RotationY="180"> <userControls:ItemsControl.ItemTemplate> <DataTemplate> ... </DataTemplate> </userControls:ItemsControl.ItemTemplate> </userControls:ItemsControl> </ScrollView>

Sign In or Register to comment.