Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Invoke method only once at end or start of carouselView is reached

Welcome, I am struggling with a complex in carousel view. I need to load items to the begging and end of a list when it is reached. I have created some solution, it seems to be a lot of bugS in there. Still it doesnt work properly on each platform. I need your help guys. Solution for now. It looks a little bit complicated because I have 2 different carouselViews, but it doesnt matter. My question is the same like in the title.

private async void CalendarOnCurrentItemChanged(object sender, ItemsViewScrolledEventArgs e)
        {
            try
            {
                if (IsBusy || _bindingContext.IsBusy)
                    return;
                IsBusy = true;
                if (_bindingContext.IsMonthView)
                {
                    var carousel = sender as CarouselView;
                    var indexOfCenterItem = e.CenterItemIndex;
                    if (carousel.ItemsSource.GetType() != typeof(ObservableCollection<CalendarMonthModel>))
                        return;
                    var items = carousel.ItemsSource.Cast<CalendarMonthModel>();

                    var properCurrent = items.ToArray()[indexOfCenterItem];
                    if (properCurrent != null)
                        _bindingContext.CurrentMonthDate = properCurrent.MonthDays.First().EntireDate;
                    _bindingContext.MonthWeeks = new ObservableCollection<MonthWeekModel>(properCurrent.MonthWeeks);
                    if (carousel == null)
                        return;
                    if (carousel.Position == 0 || properCurrent.MonthDays.First().EntireDate.Date == carousel.ItemsSource.Cast<CalendarMonthModel>().Last().MonthDays.First().EntireDate.Date)
                    {
                        if (properCurrent.MonthDays.First().EntireDate.Date == carousel.ItemsSource.Cast<CalendarMonthModel>().Last().MonthDays.First().EntireDate.Date)
                        {
                            await RightButtonLoader();
                        }
                        else if (properCurrent.MonthDays.First().EntireDate.Date == carousel.ItemsSource.Cast<CalendarMonthModel>().First().MonthDays.First().EntireDate.Date)
                        {
                            await LeftButtonLoader();
                        }
                    }
                }
                else
                {
                    if (_isIosWorkaroundWorking)
                        return;
                    var indexOfLastItem = e.LastVisibleItemIndex;
                    var indexOfFirstItem = e.FirstVisibleItemIndex;
                    var carousel = sender as CarouselView;
                    var indexOfCenter = e.CenterItemIndex;
                    if (carousel.ItemsSource.GetType() != typeof(ObservableCollection<MeetingDetailsViewModel>))
                        return;
                    var items = carousel.ItemsSource.Cast<MeetingDetailsViewModel>();
                    var properCurrentLast = items.ToArray()[indexOfLastItem];
                    var properCurrentFirst = items.ToArray()[indexOfFirstItem];
                    var properCurrentCenter = items.ToArray()[indexOfCenter];
                    if (properCurrentCenter != null)
                        _bindingContext.CurrentMonthDate = properCurrentCenter.EntireDate;

                    if (properCurrentLast.EntireDate.Date == carousel.ItemsSource.Cast<MeetingDetailsViewModel>().Last().EntireDate.Date)
                    {                       
                        await RightButtonLoader(indexOfLastItem);
                    }
                    else if (properCurrentFirst.EntireDate.Date == carousel.ItemsSource.Cast<MeetingDetailsViewModel>().First().EntireDate.Date)
                    {
                        await LeftButtonLoader(indexOfFirstItem);
                    }

                }
            }
            catch (Exception ex)
            {
               await LogService.LogAsync(ex);
            }   
            finally
            {
                IsBusy = false;
            }
        }     

Answers

  • JarvanJarvan Member, Xamarin Team Xamurai

    For the function, try detecting the PositionChanged of the CarouselView. Check if the position is 0 or the end position to add the new items.

    Check the code:

    Page.xaml.cs

    public partial class MainPage : ContentPage
    {
        CustomViewModel viewModel = new CustomViewModel();
        public MainPage()
        {
            InitializeComponent();
    
            viewModel = new CustomViewModel();
            BindingContext = viewModel;
    
        }
        private void CarouselView_PositionChanged(object sender, PositionChangedEventArgs e)
        {
            int position = e.CurrentPosition;
            if (position == 0 || position == viewModel.Data.Count - 1)
            {
                //add items to the data list
                viewModel.Data.Add(new CustomModel { ...});
                ...
            }
        }
    }
    

    Page.xaml

    <CarouselView x:Name="carouselView" ItemsSource="{Binding Data}" PositionChanged="CarouselView_PositionChanged">
        <CarouselView.ItemTemplate>
            ...
        </CarouselView.ItemTemplate>
    </CarouselView>
    

    ViewModel class

    public class CustomViewModel
    {
        public CustomViewModel()
        {
            Data = new ObservableCollection<CustomModel>() 
            {
                ... 
            };
        }
    
        public ObservableCollection<CustomModel> Data { get; set; }
    }
    
  • MasterOfXamarinMasterOfXamarin Member ✭✭✭

    @Jarvan on android it works but not always, sometimes event doesn't invoke on scroll. It seems like bug or something like that

  • JarvanJarvan Member, Xamarin Team Xamurai

    on android it works but not always, sometimes event doesn't invoke on scroll

    I tested the function and it works fine. Could you post more details about the issue? When will the event not work?

Sign In or Register to comment.