明志唯新

让 Xamarin.Forms 中 ListView 支持上滑加载更多

发表于

Xamarin.Forms 是 Xamarin 平台下的新框架,可以用一套UI代码,做多个平台的 App,得到 C# 程序员们的喜爱,毕竟这代表着生产力大幅度提升。但是正如不完美的人类永远也做不成完美的事物来,xamarin.forms 也有一些局限性(当然最新版已经支持在 Forms 中混合原生控件,解决了不少 UI 甚至 UE 上的问题)。例如,一个数据列表页面中,我们 ListView 很容易通过数据绑定手段实现列表,但是当数据足够多时就有问题了——通过 webapi 一次加载大量数据,既浪费流量也浪费时间,用户体验也很差(需要等待很久)。所以通常我们会让页面加载前面的一些数据,当用户将列表滑动到底部的时候再加载新的数据,这样循环往复可以不停的拉取新数据加载到列表中。很不幸,Xamarin.Forms 的 ListView 控件默认并不直接支持这个功能。

控件的好处是复用,所以我们可以通过继承 ListView,并稍微做一些改动调整来支持上滑到底部加载更多。代码如下:

public class InfiniteListView : ListView
{
    public static readonly BindableProperty LoadMoreCommandProperty = BindableProperty.Create(nameof(LoadMoreCommand), typeof(ICommand), typeof(InfiniteListView));

    public ICommand LoadMoreCommand
    {
        get { return (ICommand)GetValue(LoadMoreCommandProperty); }
        set { SetValue(LoadMoreCommandProperty, value); }
    }

    public InfiniteListView()
    {
        ItemAppearing += InfiniteListView_ItemAppearing;
    }

    private void InfiniteListView_ItemAppearing(object sender, ItemVisibilityEventArgs e)
    {
        var items = ItemsSource as IList;

        if (items != null && e.Item == items[items.Count - 1])
        {
            if (LoadMoreCommand != null && LoadMoreCommand.CanExecute(null))
                LoadMoreCommand.Execute(null);
        }
    }
}

在 XAML 中调用这个控件的方式如下:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    xmlns:Controls="clr-namespace:Codenutz.XF.Controls;assembly=Codenutz.XF.Controls.InfiniteListView" 
    x:Class="Codenutz.XF.InfiniteListView.Shared.View.InfiniteListViewSampleView" 
    Title="{Binding Title}">
					 
    <Controls:InfiniteListView 
        ItemsSource="{Binding MarvelCharacters}" 
        SelectedItem="{Binding SelectedCharacter}" 
        LoadMoreCommand="{Binding LoadCharactersCommand}">
    </Controls:InfiniteListView>
    
</ContentPage>

原理很简单,就是当 ListView 的最后一个 Item 显示在屏幕上时,执行加载更多命令(LoadMoreCommand)。而我们在这个命令中获取下一页数据并填充到 ListView 的绑定中即可,尤其当你用 MVVM 模式开发 App 时,这会让你很爽。你试试看就知道了。

ListView 控件在 Xamarin.Forms 的 App 中,还有不少局限,尤其是面对国内的复杂 UI 设计需求时,经常显得有点乏力,如何应对这些问题,我将在后续的文章中跟大家一起探讨。

特别声明: 本文中的控件代码并非老衣原创,而是出自http://www.codenutz.com/lac09-xamarin-forms-infinite-scrolling-listview/