question

AndreJohnson-7479 avatar image
0 Votes"
AndreJohnson-7479 asked JessieZhang-2116 edited

Cannot get CollectionView ScrollTo to work (very simple code)

I've written a very simple app to test the ScrollTo method of the CollectionView control. It just won't work no matter what I do. Would someone examine the code and tell me what I'm doing wrong?

I'm testing on an Android.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ScrollToTest.Views.MainPage"
Title="{Binding Title}">

 <StackLayout>
     <CollectionView x:Name="collectionView" 
                     ItemsSource="{Binding TestModels}"
                     SelectionMode="Single">
         <CollectionView.ItemTemplate>
             <DataTemplate>
                 <StackLayout HeightRequest="50">
                     <Label Text="{Binding Name}" FontSize="20"/>
                 </StackLayout>
             </DataTemplate>
         </CollectionView.ItemTemplate>
     </CollectionView>        
 </StackLayout>


</ContentPage>

 public partial class MainPage
 {
     public MainPage()
     {
         InitializeComponent();
     }

     protected override void OnAppearing()
     {
         base.OnAppearing();

         collectionView.ScrollTo(16);
         //collectionView.ScrollTo(16, -1, ScrollToPosition.MakeVisible, false);

         TestModel testModel = new TestModel() { Name = "Name 16" };
         //collectionView.ScrollTo(testModel);
     }
 }

public class MainPageViewModel : ViewModelBase
{
public MainPageViewModel(INavigationService navigationService) : base(navigationService)
{
Title = "Main Page";
TestModels = _testModels;
}

 public class TestModel
 {
     public string Name { get; set; }
 }

100674-scrolltotest.png
private readonly List<TestModel> _testModels = new List<TestModel>()
{
new TestModel() { Name = "Name 1" },
new TestModel() { Name = "Name 2" },
new TestModel() { Name = "Name 3" },
new TestModel() { Name = "Name 4" },
new TestModel() { Name = "Name 5" },
new TestModel() { Name = "Name 6" },
new TestModel() { Name = "Name 7" },
new TestModel() { Name = "Name 8" },
new TestModel() { Name = "Name 9" },
new TestModel() { Name = "Name 10" },
new TestModel() { Name = "Name 11" },
new TestModel() { Name = "Name 12" },
new TestModel() { Name = "Name 13" },
new TestModel() { Name = "Name 14" },
new TestModel() { Name = "Name 15" },
new TestModel() { Name = "Name 16" },
new TestModel() { Name = "Name 17" },
new TestModel() { Name = "Name 18" },
new TestModel() { Name = "Name 19" }
};

     public List<TestModel> TestModels { get; set; }
 }


dotnet-xamarin
scrolltotest.png (75.0 KiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

JessieZhang-2116 avatar image
0 Votes"
JessieZhang-2116 answered JessieZhang-2116 edited

Hello,


Welcome to our Microsoft Q&A platform!

Based on your code ,I created a simple sample,and I removed the INavigationService parameter from the constructor of MainPageViewModel

 public MainPageViewModel(INavigationService navigationService) : base(navigationService)
 {
    Title = "Main Page";
    TestModels = _testModels;
 }

The modified code of MainPageViewModel is:

     public class MainPageViewModel: ViewModelBase
     {
         public List<TestModel> TestModels { get; set; }
    
         public MainPageViewModel() 
         {
             TestModels = new List<TestModel>();
             TestModels = _testModels;
         }
    
  private readonly List<TestModel> _testModels = new List<TestModel>()
 {
 new TestModel() { Name = "Name 1" },
 new TestModel() { Name = "Name 2" },
 new TestModel() { Name = "Name 3" },
 new TestModel() { Name = "Name 4" },
 new TestModel() { Name = "Name 5" },
 new TestModel() { Name = "Name 6" },
 new TestModel() { Name = "Name 7" },
 new TestModel() { Name = "Name 8" },
 new TestModel() { Name = "Name 9" },
 new TestModel() { Name = "Name 10" },
 new TestModel() { Name = "Name 11" },
 new TestModel() { Name = "Name 12" },
 new TestModel() { Name = "Name 13" },
 new TestModel() { Name = "Name 14" },
 new TestModel() { Name = "Name 15" },
 new TestModel() { Name = "Name 16" },
 new TestModel() { Name = "Name 17" },
 new TestModel() { Name = "Name 18" },
 new TestModel() { Name = "Name 19" }
 };       
     }

And when I used code collectionView.ScrollTo(16); in method OnAppearing, it works properly.

     protected override void OnAppearing()
     {
         base.OnAppearing();

         collectionView.ScrollTo(16);
     }

And when you want to scroll to a special item of your collectionView, you can use the following code:

      protected override void OnAppearing()
     {
         base.OnAppearing();

         //collectionView.ScrollTo(16);

         MainPageViewModel viewModel = BindingContext as MainPageViewModel;
         TestModel model= viewModel.TestModels.FirstOrDefault(m => m.Name == "Name 16");
         collectionView.ScrollTo(model);
     }

And the usage as follows is not correct, because it will create a new model which is not existing in the ItemsSource of your CollectionView

         TestModel testModel = new TestModel() { Name = "Name 16" };
         collectionView.ScrollTo(testModel);

Update:

Yes , it is just the case as you said. It should be relative to Prism. When using following code in method OnAppearing, the scrollTo couldn't scroll to the special item when the page become visible for us .

     protected override void OnAppearing()
     {
         base.OnAppearing();

         MainPageViewModel viewModel = BindingContext as MainPageViewModel;
         State model = viewModel.States.FirstOrDefault(m => m.StateName == "Wyoming123");
         collectionView.ScrollTo(model);
     }

But If we add a button in this page, and call function ScrollTo in click event, it could work normlly.

        private void Button_Clicked(object sender, System.EventArgs e)
     {
         MainPageViewModel viewModel = BindingContext as MainPageViewModel;
         State model = viewModel.States.FirstOrDefault(m => m.StateName == "Wyoming123");
         collectionView.ScrollTo(model);
     }

So, you can call function ScrollTo after your page is loaded.


Best Regards,


Jessie Zhang


If the response is helpful, please click "Accept Answer" and upvote it.



Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.





· 6
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I made the changes but it still doesn't work. I'm implementing the prism toolkit so the ViewModel is automatically created. The MainPageViewModel inherits from ViewModelBase and ViewModelBase inherits from BindableBase, IInitialize, INavigationAware, IDestructible. The ViewModelBase also has in it protected INavigationService NavigationService { get; private set; }

I changed MainPageViewModel : ViewModelBase to MainPageViewModel : BindableBase so I could implement your changes. It still doesn't work but you've given me some ideas

Thanks

0 Votes 0 ·

Could you please post a basic demo to github or onedriver so that we can test on our side?

1 Vote 1 ·

Yes , it is just the case as you said. It should be relative to Prism. When using following code in method OnAppearing, the scrollTo couldn't scroll to the special item when the page become visible for us .

     protected override void OnAppearing()
     {
         base.OnAppearing();

         MainPageViewModel viewModel = BindingContext as MainPageViewModel;
         State model = viewModel.States.FirstOrDefault(m => m.StateName == "Wyoming123");
         collectionView.ScrollTo(model);
     }

But If we add a button in this page, and call function ScrollTo in click event, it could work normlly.

        private void Button_Clicked(object sender, System.EventArgs e)
     {
         MainPageViewModel viewModel = BindingContext as MainPageViewModel;
         State model = viewModel.States.FirstOrDefault(m => m.StateName == "Wyoming123");
         collectionView.ScrollTo(model);
     }

1 Vote 1 ·

Thanks for the help. In my actual project I wanted the state to be selected when the page loaded, but since I couldn't make that work I went with the clicked event. There is label above the list of states with the text "Select A State". I added a gesture to the label which scrolls to the default state. My client is ok with that.

0 Votes 0 ·

As a summary, I updated my reply with the latest solution at the bottom of my answer so that it will help others who have similar problems. Thanks for your support for xamarin.

1 Vote 1 ·