ListView の対話機能
Xamarin.FormsListView
クラスは、ユーザーが提示するデータとの操作をサポートします。
選択とタップ
ListView
選択モードは、ListView.SelectionMode
プロパティを列挙型の ListViewSelectionMode
値に設定することによって制御されます:
ユーザーが項目をタップすると、次の 2 つのイベントが発生します:
ItemSelected
は、新しい項目が選択されたときに発生します。ItemTapped
は、項目がタップされたときに発生します。
同じアイテムを 2 回タップすると、2 つの ItemTapped
イベントが発生しますが、1 つの ItemSelected
イベントのみが発生します。
Note
ItemTapped
イベントのイベント引数を含む ItemTappedEventArgs
クラスには、Group
と Item
プロパティと、タップされたアイテムの ListView
内のインデックスを表す値を持つ ItemIndex
プロパティがあります。 同様に、ItemSelected
イベントのイベント引数を含む SelectedItemChangedEventArgs
クラスには、 SelectedItem
プロパティと、選択した項目の ListView
内のインデックスを表す値を持つ SelectedItemIndex
プロパティがあります。
SelectionMode
プロパティが Single
に設定されている場合、ListView
内の項目を選択すると、ItemSelected
イベントと ItemTapped
イベントが発生し、SelectedItem
プロパティが選択した項目の値に設定されます。
SelectionMode
プロパティが None
に設定されている場合、 ListView
内の項目を選択することはできません。ItemSelected
イベントは発生せず、SelectedItem
プロパティは null
のままです。 ただし、ItemTapped
イベントは引き続き発生し、タップした項目はタップ中に一時的に強調表示されます。
項目が選択され、SelectionMode
プロパティが Single
から None
に変更されると、SelectedItem
プロパティは null
に設定され、ItemSelected
イベントは null
項目で発生します。
次のスクリーンショットは、既定の ListView
選択モードを示しています:
選択を無効にする
ListView
選択を無効にするには、SelectionMode
プロパティを None
に設定します:
<ListView ... SelectionMode="None" />
var listView = new ListView { ... SelectionMode = ListViewSelectionMode.None };
コンテキスト アクション
多くの場合、ユーザーは ListView
内のアイテムに対してアクションを実行する必要があります。 たとえば、メール アプリのメールの一覧を考えてみましょう。 iOS では、スワイプしてメッセージを削除できます:
コンテキスト アクションは、C# と XAML で実装できます。 次に、両方の具体的なガイドを示しますが、まず、両方の主要な実装の詳細を見てみましょう。
コンテキスト アクションは、MenuItem
要素を使用して作成されます。 MenuItems
オブジェクトのタップ イベントは、ListView
ではなく、MenuItem
自体によって発生します。 これは、セルに対してタップ イベントを処理する方法とは異なり、ListView
はセルではなくイベントを発生させます。 ListView
はイベントを発生させているため、そのイベント ハンドラーには、選択またはタップされた項目などのキー情報が与えられます。
既定では、MenuItem
はどのセルに属するかを知る方法はありません。 CommandParameter
プロパティは、MenuItem
の ViewCell
の背後にあるオブジェクトなど、オブジェクトを格納する MenuItem
で使用できます。 CommandParameter
プロパティは、XAML と C# の両方で設定できます。
XAML
MenuItem
要素は XAML コレクション内に作成できます。 次の XAML は、2 つのコンテキスト アクションが実装されたカスタム セルを示しています:
<ListView x:Name="ContextDemoList">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Clicked="OnMore"
CommandParameter="{Binding .}"
Text="More" />
<MenuItem Clicked="OnDelete"
CommandParameter="{Binding .}"
Text="Delete" IsDestructive="True" />
</ViewCell.ContextActions>
<StackLayout Padding="15,0">
<Label Text="{Binding title}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
分離コード ファイルで、Clicked
メソッドが実装されていることを確認します:
public void OnMore (object sender, EventArgs e)
{
var mi = ((MenuItem)sender);
DisplayAlert("More Context Action", mi.CommandParameter + " more context action", "OK");
}
public void OnDelete (object sender, EventArgs e)
{
var mi = ((MenuItem)sender);
DisplayAlert("Delete Context Action", mi.CommandParameter + " delete context action", "OK");
}
Note
Android 用 NavigationPageRenderer
には、カスタム Drawable
からアイコンを読み込むのに使用できるオーバーライド可能な UpdateMenuItemIcon
メソッドがあります。 このオーバーライドにより、Android 上の MenuItem
インスタンスのアイコンとして SVG 画像を使用できます。
コード
コンテキスト アクションは、MenuItem
インスタンスを作成し、セルの ContextActions
コレクションに追加することで、(グループ ヘッダーとして使用されていない限り) 任意の Cell
サブクラスに実装できます。 コンテキスト アクションには、次のプロパティを構成できます:
- Text – メニュー項目に表示される文字列。
- Clicked – 項目がクリックされたときのイベント。
- IsDestructive – (オプション) true の場合、iOS で項目が異なる方法でレンダリングされます。
複数のコンテキスト アクションを 1 つのセルに追加できますが、IsDestructive
を true
に設定する必要があるのは 1 つだけです。 次のコードは、コンテキスト アクションを ViewCell
に追加する方法を示しています:
var moreAction = new MenuItem { Text = "More" };
moreAction.SetBinding (MenuItem.CommandParameterProperty, new Binding ("."));
moreAction.Clicked += async (sender, e) =>
{
var mi = ((MenuItem)sender);
Debug.WriteLine("More Context Action clicked: " + mi.CommandParameter);
};
var deleteAction = new MenuItem { Text = "Delete", IsDestructive = true }; // red background
deleteAction.SetBinding (MenuItem.CommandParameterProperty, new Binding ("."));
deleteAction.Clicked += async (sender, e) =>
{
var mi = ((MenuItem)sender);
Debug.WriteLine("Delete Context Action clicked: " + mi.CommandParameter);
};
// add to the ViewCell's ContextActions property
ContextActions.Add (moreAction);
ContextActions.Add (deleteAction);
引っ張って更新
ユーザーは、データの一覧をプルダウンすると、その一覧が更新されることを期待するようになりました。 ListView
コントロールでは、これをデフォルトでサポートしています。 プル更新機能を有効にするには、IsPullToRefreshEnabled
を true
に設定します:
<ListView ...
IsPullToRefreshEnabled="true" />
同等の C# コードを次に示します。
listView.IsPullToRefreshEnabled = true;
更新中にスピナーが表示されます。既定値は黒です。 ただし、iOS および Android では、RefreshControlColor
プロパティを Color
に設定することで、スピナーの色を変更できます:
<ListView ...
IsPullToRefreshEnabled="true"
RefreshControlColor="Red" />
同等の C# コードを次に示します。
listView.RefreshControlColor = Color.Red;
次のスクリーンショットは、ユーザーがプルしている間のプルして更新を示しています:
次のスクリーンショットは、ユーザーがプルを解放した後のプルして更新を示しています。ListView
の更新中にスピナーが表示されています:
ListView
は Refreshing
イベントを発生させて更新を開始し、IsRefreshing
プロパティが true
に設定されます。 ListView
の内容を更新するために必要なコードは、Refreshing
イベントのイベント ハンドラーまたは RefreshCommand
によって実行されるメソッドによって実行される必要があります。 ListView
が更新されたら、IsRefreshing
プロパティを false
に設定するか、EndRefresh
メソッドを呼び出して、更新が完了したことを示す必要があります。
Note
RefreshCommand
を定義する場合、コマンドの CanExecute
メソッドを指定して、コマンドを有効または無効にすることができます。
スクロールの検出
ListView
は、スクロールが発生したことを示すために発生する Scrolled
イベントを定義します。 次の XAML の例は、Scrolled
イベントのイベント ハンドラーを設定する ListView
を示しています。
<ListView Scrolled="OnListViewScrolled">
...
</ListView>
同等の C# コードを次に示します。
ListView listView = new ListView();
listView.Scrolled += OnListViewScrolled;
このコード例では、Scrolled
イベントが発生すると、OnListViewScrolled
イベント ハンドラーが実行されます。
void OnListViewScrolled(object sender, ScrolledEventArgs e)
{
Debug.WriteLine("ScrollX: " + e.ScrollX);
Debug.WriteLine("ScrollY: " + e.ScrollY);
}
OnListViewScrolled
イベント ハンドラーは、イベントに付随する ScrolledEventArgs
オブジェクトの値を出力します。