Xamarin.forms 以每结果十项为增量加载数据Xamarin表单

Xamarin.forms 以每结果十项为增量加载数据Xamarin表单,xamarin.forms,Xamarin.forms,我试图构建一个请求,每次从服务器为每个请求加载10个项目。例如,当用户单击一个按钮,将其重定向到下一页时,我希望前10个项目首先显示,而对其他项目的请求则在后台进行。我该怎么做呢?我知道它是如何工作的,在服务器端,通过设置每个请求返回的最大数量和起始位置,但这是正确的方法吗?是的,这听起来是一个处理它的好方法。这通常称为数据的“分页” 让API处理要接收的数据“页面”的偏移量以及该页面要返回的最大项数(pagesize)。下面是一个如何为表单实现此功能的示例 ViewModel要实现的合同:

我试图构建一个请求,每次从服务器为每个请求加载10个项目。例如,当用户单击一个按钮,将其重定向到下一页时,我希望前10个项目首先显示,而对其他项目的请求则在后台进行。我该怎么做呢?我知道它是如何工作的,在服务器端,通过设置每个请求返回的最大数量和起始位置,但这是正确的方法吗?

是的,这听起来是一个处理它的好方法。这通常称为数据的“分页”

让API处理要接收的数据“页面”的偏移量以及该页面要返回的最大项数(pagesize)。下面是一个如何为表单实现此功能的示例

ViewModel要实现的合同:

ViewModel中的一个示例实现:

#region ISupportIncrementalLoading Implementation

public int PageSize { get; set; } = 10;

public bool HasMoreItems { get; set; }

public async Task LoadMoreItemsAsync()
{
    await LoadMoreItemsCommand.ExecuteAsyncTask();
}

//...

#endregion
示例LoadMoreItemsCommand:

LoadMoreItemsCommand = new Command(async () =>
{
    int fetchOffset = Requests.Count;
    int fetchMax = PageSize;

    // "Pagination" of your API request starting at the offset
    // and getting a maximum of the `fetchMax` or "page size"
    Results = await GetRequestsAsync(fetchOffset, fetchMax);
});
要在控件(如
ListView
中自动支持此操作,可以自定义渲染器或“效果”来实现此操作。以下是一个删减的示例:

// Custom ListViewRenderer, iOS example
public class IncrementalListViewRenderer : ListViewRenderer
{
    public IncrementalListViewRenderer()
    {
    }

    protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
    {
        base.OnElementChanged(e);

        if (Control != null)
        {
            // Need to customize the source but not lose existing functionality so 
            // we need a copy of it to use
            UITableViewSource defaultSource = Control.Source;            
            Control.Source = new IncrementalDataSource(Element as IncrementalListView, defaultSource);            
        }
    }

    class IncrementalDataSource : UITableViewSource
    {
        readonly UITableViewSource existingSource;
        readonly IncrementalListView listView;
        readonly ISupportIncrementalLoading incrementalLoading;

        int lastPosition;
        int preloadMargin = 5;

        public IncrementalDataSource(IncrementalListView listView, UITableViewSource existingSource)
        {
            this.listView = listView;
            this.existingSource = existingSource;

            incrementalLoading = listView.BindingContext as ISupportIncrementalLoading;

            lastPosition = 0;

            LoadMoreItems();
        }

        public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
        {
            int position = indexPath.Row;
            var itemsSource = listView.ItemsSource as IList;

            if (itemsSource != null)
            {
                int preloadIndex = Math.Max(itemsSource.Count - preloadMargin, 0);

                if ((position > lastPosition || (position == itemsSource.Count - 1)) && (position >= preloadIndex))
                {
                    lastPosition = position;

                    if(!incrementalLoading.IsLoading && incrementalLoading.HasMoreItems)
                        LoadMoreItems();
                }
            }

            var cell = existingSource.GetCell(tableView, indexPath);
            cell.SelectionStyle = UITableViewCellSelectionStyle.None;

            return cell;
        }

        public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
        {
            existingSource.RowSelected(tableView, indexPath);
        }

        public override nint RowsInSection(UITableView tableview, nint section)
        {
            return existingSource.RowsInSection(tableview, section);
        }

        void LoadMoreItems()
        {
            // Note the use of Nito.AsyncEx lib
            INotifyTaskCompletion taskCompletion = NotifyTaskCompletion.Create(LoadMoreItemsAsync());
        }

        public async Task LoadMoreItemsAsync()
        {
            await incrementalLoading.LoadMoreItemsAsync();
        }
    }
}
//自定义ListViewRenderer,iOS示例
公共类IncrementalListViewRenderer:ListViewRenderer
{
public IncrementalListViewRenderer()
{
}
受保护的覆盖无效OnElementChanged(ElementChangedEventArgs e)
{
基础。一个要素发生变化(e);
if(控件!=null)
{
//需要自定义源代码,但不丢失现有功能,以便
//我们需要一份副本来使用
UITableViewSource defaultSource=Control.Source;
Control.Source=新的IncrementalDataSource(元素为IncrementalListView,defaultSource);
}
}
类IncrementalDataSource:UITableViewSource
{
只读UITableViewSource现有源;
只读递增列表视图列表视图;
只读支持递增加载递增加载;
最后位置;
int预加裕度=5;
公共增量数据源(增量列表视图列表视图,UITableViewSource现有源)
{
this.listView=listView;
this.existingSource=existingSource;
incrementalLoading=listView.BindingContext作为ISupportIncrementalLoading;
lastPosition=0;
loadmoreems();
}
公共覆盖UITableViewCell GetCell(UITableView tableView,NSIndexPath indexPath)
{
int position=indexPath.Row;
var itemsSource=listView.itemsSource作为IList;
如果(itemsSource!=null)
{
int preload index=Math.Max(itemsSource.Count-preload-margin,0);
if((position>lastPosition | | |(position==itemsSource.Count-1))&&(position>=preload index))
{
最后位置=位置;
如果(!incrementalLoading.IsLoading&&incrementalLoading.HasMoreItems)
loadmoreems();
}
}
var cell=existingSource.GetCell(tableView,indexPath);
cell.SelectionStyle=UITableViewCellSelectionStyle.None;
返回单元;
}
public override void RowSelected(UITableView tableView,NSIndexPath indexPath)
{
existingSource.RowSelected(tableView,indexPath);
}
公共覆盖第九行第九节(UITableView表格视图,第九节)
{
返回existingSource.RowsInSection(tableview,section);
}
void LoadMoreItems()
{
//请注意Nito.AsyncEx lib的使用
INotifyTaskCompletion taskCompletion=NotifyTaskCompletion.Create(LoadMoreItemsAsync());
}
公共异步任务LoadMoreItemsAsync()
{
等待incrementalLoading.LoadMoreItemsAsync();
}
}
}
这充分利用了插件的技术

// Custom ListViewRenderer, iOS example
public class IncrementalListViewRenderer : ListViewRenderer
{
    public IncrementalListViewRenderer()
    {
    }

    protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
    {
        base.OnElementChanged(e);

        if (Control != null)
        {
            // Need to customize the source but not lose existing functionality so 
            // we need a copy of it to use
            UITableViewSource defaultSource = Control.Source;            
            Control.Source = new IncrementalDataSource(Element as IncrementalListView, defaultSource);            
        }
    }

    class IncrementalDataSource : UITableViewSource
    {
        readonly UITableViewSource existingSource;
        readonly IncrementalListView listView;
        readonly ISupportIncrementalLoading incrementalLoading;

        int lastPosition;
        int preloadMargin = 5;

        public IncrementalDataSource(IncrementalListView listView, UITableViewSource existingSource)
        {
            this.listView = listView;
            this.existingSource = existingSource;

            incrementalLoading = listView.BindingContext as ISupportIncrementalLoading;

            lastPosition = 0;

            LoadMoreItems();
        }

        public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
        {
            int position = indexPath.Row;
            var itemsSource = listView.ItemsSource as IList;

            if (itemsSource != null)
            {
                int preloadIndex = Math.Max(itemsSource.Count - preloadMargin, 0);

                if ((position > lastPosition || (position == itemsSource.Count - 1)) && (position >= preloadIndex))
                {
                    lastPosition = position;

                    if(!incrementalLoading.IsLoading && incrementalLoading.HasMoreItems)
                        LoadMoreItems();
                }
            }

            var cell = existingSource.GetCell(tableView, indexPath);
            cell.SelectionStyle = UITableViewCellSelectionStyle.None;

            return cell;
        }

        public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
        {
            existingSource.RowSelected(tableView, indexPath);
        }

        public override nint RowsInSection(UITableView tableview, nint section)
        {
            return existingSource.RowsInSection(tableview, section);
        }

        void LoadMoreItems()
        {
            // Note the use of Nito.AsyncEx lib
            INotifyTaskCompletion taskCompletion = NotifyTaskCompletion.Create(LoadMoreItemsAsync());
        }

        public async Task LoadMoreItemsAsync()
        {
            await incrementalLoading.LoadMoreItemsAsync();
        }
    }
}