I have been created ListView that has infinite scrolling with help on ObservableRangeCollection. It works good on Android, but on iOS it jumps to start whenever it adds new items. Paginating is done with behavior. ListView is a FlowListView. Here is XAML:
...FlowItemsSource="{Binding Profiles.Result}...<controls:FlowListView.Behaviors><behaviors:FlowListViewPaginating Command="{Binding LoadMoreCommand}" Converter="{StaticResource ItemVisibilityConverter}"></behaviors:FlowListViewPaginating></controls:FlowListView.Behaviors>...
Behavior:
public class FlowListViewPaginating : Behavior<FlowListView> { public FlowListView AssosiatedObject { get; private set; } public static readonly BindableProperty CommandProperty = BindableProperty.Create("Command", typeof(DelegateCommand<Profile>), typeof(FlowListViewPaginating), null); public static readonly BindableProperty InputConverterProperty = BindableProperty.Create("Converter", typeof(IValueConverter), typeof(FlowListViewPaginating), null); public DelegateCommand<Profile> Command { get { return ( DelegateCommand<Profile> )GetValue(CommandProperty); } set { SetValue(CommandProperty, value); } } public IValueConverter Converter { get { return ( IValueConverter )GetValue(InputConverterProperty); } set { SetValue(InputConverterProperty, value); } } protected override void OnAttachedTo(FlowListView bindable) { base.OnAttachedTo(bindable); AssosiatedObject = bindable; bindable.BindingContextChanged += OnBindingContextChanged; bindable.ItemAppearing += OnItemAppearing; } protected override void OnDetachingFrom(FlowListView bindable) { base.OnDetachingFrom(bindable); bindable.BindingContextChanged -= OnBindingContextChanged; bindable.ItemAppearing -= OnItemAppearing; AssosiatedObject = null; } private void OnItemAppearing(object sender, ItemVisibilityEventArgs e) { var flowListView = ( FlowListView )sender; if ( flowListView.IsRefreshing ) return; if ( Command == null ) return; var parameter = Converter.Convert(e, typeof(object), null, null) as Profile; if ( Command.CanExecute(parameter) ) Command.Execute(parameter); } protected void OnBindingContextChanged(object sender, EventArgs e) { OnBindingContextChanged(); } protected override void OnBindingContextChanged() { base.OnBindingContextChanged(); BindingContext = AssosiatedObject.BindingContext; } }
Converter for Behavior:
public class ItemVisibilityEventConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var eventArgs = value as ItemVisibilityEventArgs; var collection = eventArgs?.Item as System.Collections.ObjectModel.ObservableCollection<object>; return collection[0]; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
My collection:
public NotifyTask<ObservableRangeCollection<Profile>> Profiles { get; set; }
NotifyTask
has nothing to do with the collection. It is just a wrapper.
A method where I add items:
private async Task OnLoadMore(Profile lastProfile) { IsBusy = true; _pageNumber++; Profiles.Result.AddRange(await _manager.GetProfilesAsync(_parameters.NextPage())); IsBusy = false; }