Quantcast
Channel: Xamarin 日本語情報
Viewing all articles
Browse latest Browse all 233

Xamarin.Forms で CollectionView を使うには

$
0
0

こんにちは。エクセルソフトの田淵です。

すっかり放置のブログですが、せっかくの Xamarin Advent Calendar 2020なので多少はコンテンツを出していかないとですよね…!2日目です。

1日目は @the_uhooiさんの 単体テストを書くクラスでXamarin.*を呼び出してはいけない(Xamarin) - Qiita、3日目は @atsushienoさんの Xamarin.Android fast deployment v2についてです。

Xamarin.Forms もどんどん進化しており、チェックボックスができたり、新しいビューが出来たりしています。そこで少しずつ新しいビューの紹介をしていこうと思います。

CollectionView

ということで CollectionView です。

詳しくは 公式ドキュメント Xamarin.Forms CollectionView - Xamarin | Microsoft Docsを見ていただきたいのですが、2020年11月末の時点で自動日本語訳がなかなかの出来映えですねw 分かりにくかったら英語で読む方が良いかもしれません。

f:id:ytabuchi:20201124173938p:plain:w450

従来の ListViewをより使いやすくしたコレクションを表示するビューで、基本的な使い方は ListViewとほぼ同じです。主な違いは

  • データを垂直方向または水平方向にリストまたはグリッドで表示できるレイアウト
  • 単一および複数の選択をサポート
  • Cell ではなく DataTemplateを使用して、データの表示方法を定義
  • CachingStrategyが標準でオンで、ネイティブの仮想化を利用
  • 表示に関するプロパティやイベントを少なく(DataTemplateでカバー)
  • Separatorを削除(DataTemplateでカバー)
  • ItemsSourceが UI スレッドから更新された場合に例外をスロー

です。

サンプルをアップしておきました。

github.com

データと表示

ListViewと同様に、IEnumerable<T>のコレクションを ItemsSourceに指定します。一般的には Binding することになります。

データについては Xamarin.Forms CollectionView のデータ - Xamarin | Microsoft Docs、レイアウトについては Xamarin.Forms CollectionView のレイアウト - Xamarin | Microsoft Docsを参照してください。

XAML は例えば次のようになります。

<CollectionView ItemsLayout="VerticalGrid, 2"ItemsSource="{Binding}"><CollectionView.ItemTemplate><DataTemplate><Grid><Grid.RowDefinitions><RowDefinition Height="Auto" /><RowDefinition Height="*" /><RowDefinition Height="Auto" /></Grid.RowDefinitions><Image Grid.Row="0"Grid.RowSpan="3"WidthRequest="180"HeightRequest="180"Aspect="AspectFill"Source="{Binding ImageUrl}" /><BoxView Grid.Row="0"HeightRequest="5"BackgroundColor="Black"Opacity="0.6" /><Label Grid.Row="0"Padding="5,0"FontAttributes="Bold"Text="{Binding Name}"TextColor="White" /><BoxView Grid.Row="2"HeightRequest="5"BackgroundColor="Black"Opacity="0.4" /><Label Grid.Row="2"Padding="5,0"VerticalOptions="End"FontAttributes="Italic"Text="{Binding Location}"TextColor="White" /></Grid></DataTemplate></CollectionView.ItemTemplate></CollectionView>

ItemsLayoutには、VerticalListHorizontalListVerticalGridHorizontalGridを指定できます。Grid は並べる数を同時に指定します。

<CollectionView.ItemsLayout><GridItemsLayout HorizontalItemSpacing="2"Orientation="Vertical"Span="2"VerticalItemSpacing="2" /></CollectionView.ItemsLayout>

のように別途アイテムレイアウトを指定することもできます。

以下のような感じで表示されます。

f:id:ytabuchi:20201127173641p:plain:w300

選択

項目の選択はいくつかのやり方があります。SelectionModeが規定では Noneなので選択できるように Singleまたは Multipleを指定します。

詳細は Xamarin.Forms CollectionView の選択 - Xamarin | Microsoft Docsを参照してください。

アイテムが選択されると、SelectedItem プロパティは選択されたアイテムの値に設定されます。 このプロパティが変更されると、SelectionChangedCommand が実行され(SelectionChangedCommandParameter の値が ICommand に渡されます)、SelectionChanged イベントが発生します。

とドキュメントにありますので、イベントハンドラーまたはコマンドで処理をすることになります。

ここでは SelectionModeSingleの場合の例を記載します。

コードビハインド

コードビハインドで記述する場合は、SelectionChangedイベントをイベントハンドラーで拾うのが良いでしょう。SelectionChangedEventArgsCurrentSelectionPreviousSelectionのプロパティを利用できます。

privatevoid OnCollectionViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var previous = (e.PreviousSelection.FirstOrDefault() as Monkey)?.Name;
    var current = (e.CurrentSelection.FirstOrDefault() as Monkey)?.Name;
}

SelectionModeMultipleの場合は、SelectionChangedEventArgsIEnumerable<object>のコレクションとして取得できるので、サンプルの GitHubにあるように、適宜処理すると良いでしょう。

ViewModel

ViewModel で処理をする場合は、SelectionChangedCommandSelectedItemをバインドするのが良さそうです。

<CollectionView ItemsSource="{Binding Monkeys}"SelectedItem="{Binding SelectedMonkey}"SelectionChangedCommand="{Binding SelectionChangedCommand}"SelectionMode="Single">

XAML を上記のように記載した場合は、項目が選択されると SelectedItemに選択された項目がセットされ、SelectionChangedCommandが実行されます。ViewModel 側ではプロパティとコマンドをバインディングして、

private Monkey selectedMonkey;
public Monkey SelectedMonkey
{
    get { return selectedMonkey; }
    set { SetProperty(ref selectedMonkey, value); }
}
public DelegateCommand SelectionChangedCommand { get; private set; }

コマンドでは SelectedMonkeyに応じて処理を行うのが良さそうです。

SelectionChangedCommand = new DelegateCommand(() =>
{
    Debug.WriteLine($"{SelectedMonkey.Name} is selected");
});

本当は SelectionChangedCommandParameterに選択項目の値をバインディングしたかったのですが、やり方が分かりませんでした。。わかる方はコメントください。。

EmptyView

表示するデータがない場合にユーザーフィードバックを提供する EmptyViewが用意されています。

詳細は Xamarin.Forms CollectionView の EmptyView - Xamarin | Microsoft Docsを参照して下さい。

直接以下のように String を渡すか、

<CollectionView ItemsSource="{Binding EmptyMonkeys}"
                EmptyView="No items to display" />

XAML で定義することが出来ます。

<CollectionView.EmptyView><ContentView><StackLayout HorizontalOptions="CenterAndExpand"VerticalOptions="CenterAndExpand"><Label Text="No results matched your filter."Margin="10,25,10,10"FontAttributes="Bold"FontSize="18"HorizontalOptions="Fill"HorizontalTextAlignment="Center" /><Label Text="Try a broader filter?"FontAttributes="Italic"FontSize="12"HorizontalOptions="Fill"HorizontalTextAlignment="Center" /></StackLayout></ContentView></CollectionView.EmptyView>

その他、Xamarin.Forms CollectionView の スクロール - Xamarin | Microsoft DocsXamarin.Forms CollectionView の グループ化 - Xamarin | Microsoft Docsなどもあります。

まとめ

ListView では実現できなかった、Gird 表示でのコレクション表示が標準でサポートされるようになりました。ぜひ活用してください!

TIPS

XAML Navigation

Prism.Forms v7.1 で XAML Navigation が追加されました。(リリースノートの「#1425: XAML Navigation」の部分)

ContentPage の Attribute に xmlns:prism="http://prismlibrary.com"を追加して、

<Button Command="{prism:NavigateTo 'path/to/navigate'}"Text="Push me" />

と記述すると、ViewModel にコマンドを用意しなくてもページ遷移できます。

パラメーターも XAML だけで渡せます。詳しくはドキュメント Xaml Navigation | Prismを参照してください。

以上です。


Viewing all articles
Browse latest Browse all 233

Trending Articles