刷新跳转到第一项后iOS上的无限ListView

时间:2017-02-01 11:18:38

标签: listview xamarin xamarin.ios xamarin.forms observablecollection

我已经创建了ListView,它有无限滚动和ObservableRangeCollection的帮助。它在Android上运行良好,但在iOS上它会在添加新项目时跳转。分页是通过行为来完成的。 ListView是一个FlowListView。 这是XAML:

...
FlowItemsSource="{Binding Profiles.Result}
...
<controls:FlowListView.Behaviors>
        <behaviors:FlowListViewPaginating
          Command="{Binding LoadMoreCommand}"
          Converter="{StaticResource ItemVisibilityConverter}">
        </behaviors:FlowListViewPaginating>
      </controls:FlowListView.Behaviors>
...

行为:

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;
        }


    }

行为转换器:

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();
        }
    }

我的收藏:

public NotifyTask<ObservableRangeCollection<Profile>> Profiles { get; set; }

NotifyTask与该集合无关。它只是一个包装。

我添加项目的方法:

private async Task OnLoadMore(Profile lastProfile)
        {
            IsBusy = true;
            _pageNumber++;
            Profiles.Result.AddRange(await _manager.GetProfilesAsync(_parameters.NextPage()));
            IsBusy = false;
        }

2 个答案:

答案 0 :(得分:2)

当项目更新时,这些示例不会在iOS / Android上滚动您的列表。请务必使用最新的nuget包。

XAML:

<flv:FlowListView FlowColumnCount="3" SeparatorVisibility="None" HasUnevenRows="false"
    FlowItemTappedCommand="{Binding ItemTappedCommand}" FlowLastTappedItem="{Binding LastTappedItem}"
    FlowItemsSource="{Binding Items}" Grid.ColumnSpan="2">

    <flv:FlowListView.FlowColumnTemplate>
        <DataTemplate>
            <Label HorizontalOptions="Fill" VerticalOptions="Fill" 
                XAlign="Center" YAlign="Center" Text="{Binding Title}"/>
        </DataTemplate>
    </flv:FlowListView.FlowColumnTemplate>

</flv:FlowListView>

查看型号:

public UpdateItemsPageModel()
{
    AddCommand = new BaseCommand((arg) =>
    {
        insertId++;
        Items.Insert(10, new SimpleItem() { Title = string.Format("New {0}", insertId) }); 
    });

    RemoveCommand = new BaseCommand((arg) =>
    {
        Items.RemoveAt(10);
    });
}

public ObservableCollection<object> Items
{
    get { return GetField<ObservableCollection<object>>(); }
    set { SetField(value); }
}

答案 1 :(得分:0)

我在我的情况下找到了解决方法。这是代码,当它工作正常时:

private void OnLoadMore(Profile lastProfile)
        {
            IsBusy = true;
            _pageNumber++;

            Device.BeginInvokeOnMainThread(async () =>
            {
                var newItems = await _manager.GetProfilesAsync(_parameters.NextPage());
                Profiles.Result.AddRange(newItems);
            });

            IsBusy = false;
        }

还有一个问题。它没有显示加载指示器。在iOS和Android上。如果我将该方法的其余代码放在主线程中,或者从主线程移动GetProfilesAsync,它将像以前一样跳转。