Xamarin.Formsでスマホアプリ開発

C#Xamarin.Formsでスマホ開発#35 ListViewを下に引っ張て更新する方法

ListViewを下に引っ張て更新とは?

ListViewが表示されているときに,上から下にスワイプすることで,ListViewに対して更新を促すことができます。スマホを使い慣れている方ならわかると思いますが,下に引っ張って更新される動作です。AndroidやiOSでこの動作は可能ですが,Windowsにこの思想がないと思うので,UWPでは普通にやってもできません。何かツールを使うとできるかもしれませんが,今回はAndroidだけで検証します。

準備

今回はPullToRefreshPageというコンテンツページを作成して検証していきたいと思います。ここまで順番に解説をよんでいただいている方は,PullToRefreshPage という新規のコンテンツページを作って,ControlsPageから呼び出せるようにしてください。ここから初めて読んでいる方は,Xamarin.Formsのデフォルトで作成されるMainPageにPullToRefreshPageの実装をして問題ありません。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using XSample.Objects;

namespace XSample.Pages
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class MenuPage : ContentPage
    {
        public MenuPage ()
        {
            InitializeComponent ();

            var dtos = new List<MenuDto>();
            dtos.Add(new MenuDto("ControlsPage", "コントロールの一覧", "mail.png"));
            dtos.Add(new MenuDto("PullToRefreshPage", "ListViewを下に引っ張て更新", "mail.png"));
            MyListView.ItemsSource = dtos;
        }

        private void MyListView_ItemTapped(object sender, ItemTappedEventArgs e)
        {
            var item = e.Item as MenuDto;
            //DisplayAlert(item.Title, item.SubTitle, "OK");

            if (item.Title == "ControlsPage")
            {
                Navigation.PushAsync(new ControlsPage());
            }
            else if (item.Title == "PullToRefreshPage")
            {
                Navigation.PushAsync(new PullToRefreshPage());
            }
        }
    }
}

PullToRefreshPageの追加

Pagesフォルダーに新規追加でPullToRefreshPageという名前のコンテンツページを作成してください。作成されたらデフォルトのラベルを削除して,次のように記述します。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XSample.Pages.PullToRefreshPage">
    <ContentPage.Content>
        <StackLayout>

            <ListView x:Name="MyListView"
                      IsPullToRefreshEnabled="True"
                      Refreshing="MyListView_Refreshing">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextCell Text="{Binding Name}">
                        </TextCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

とりあえず普通にListViewを作成します。IsPullToRefreshEnabledをTrueにしておくことで,下に引っ張って更新ができるようになります。Refreshingイベントは下に引っ張って更新を促されたときに通知されます。Refreshingイベントの中にListViewを更新する処理を書いておきましょう。

コードビハインド側の実装

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace XSample.Pages
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class PullToRefreshPage : ContentPage
    {
        private ObservableCollection<PullToRefreshDto> _dtos = new ObservableCollection<PullToRefreshDto>();
        public PullToRefreshPage ()
        {
            InitializeComponent ();

            _dtos.Add(new PullToRefreshDto(DateTime.Now.ToString()));
            MyListView.ItemsSource = _dtos;
        }

        private async void MyListView_Refreshing(object sender, EventArgs e)
        {
            await Task.Run(() => System.Threading.Thread.Sleep(3000));
            _dtos.Add(new PullToRefreshDto(DateTime.Now.ToString()));
            MyListView.EndRefresh();
        }
    }

    public class PullToRefreshDto
    {
        public PullToRefreshDto(string name)
        {
            Name = name;
        }

        public string Name { get; set; }
    }
}

コードビハインド側にはPullToRefreshDtoというクラスを作り,ListViewにバインドします。中身はNameというstringのプロパティのみです。ここには今回はシステム日時の文字列を入れておきます。コンストラクタでリストを作成しMyListViewのItemsSourceにセットします。最初のリストは1件です。Refreshingイベントには,リストの更新処理を書きますが,今回は検証のために,リストを1件追加する処理を書きます。リストの追加はすぐに終わってしまうので,少し更新に時間がかかるようにするために,3秒間のウエイトを入れています。そのままSleepさせると画面が固まってしまうので非同期でSleepさせています。

実行

この状態で実行し,下に引っ張って更新をすると,リストが1件増える動作をすることが確認できます。

Xamarin.Formsでスマホアプリ開発