Xamarin.Forms CollectionView の選択

CollectionView は、項目の選択を制御する次のプロパティを定義します。

  • SelectionMode 型の SelectionMode は、選択モードです。
  • object 型の SelectedItem は、リストで選択された項目です。 このプロパティは、規定のバインディング モードが TwoWayで、項目が選択されていないときは null の値を持ちます。
  • IList<object> 型の SelectedItems は、リスト内の選択項目です。 このプロパティは、既定のバインディング モードが OneWayで、項目が選択されていないときは null の値を持っています。
  • ICommand 型の SelectionChangedCommand は、選択された項目が変更されたときに実行されます。
  • SelectionChangedCommandParameter: object 型、SelectionChangedCommand に渡されるパラメーター。

これらのプロパティはすべて、BindableProperty オブジェクトを基盤としています。つまり、プロパティはデータ バインディングの対象にすることができます。

既定では、CollectionView の選択は無効になっています。 しかしこの動作は、SelectionMode プロパティの値をSelectionMode 列挙要素のいずれかに設定することで変更できます:

  • None - 項目が選択できないことを示します。 これが既定値です。
  • Single - 選択した項目が強調表示された状態で、1 つの項目を選択できることを示します。
  • Multiple - 選択した項目が強調表示された状態で、複数の項目を選択できることを示します。

CollectionView は、ユーザーがリストから項目を選択したことにより、またはアプリケーションがプロパティを設定したことにより、SelectedItem プロパティが変更されたときに発生するSelectionChanged イベントを定義します。 さらに、このイベントは、SelectedItems プロパティが変更されたときにも発生します。 SelectionChanged イベントに付随する SelectionChangedEventArgs オブジェクトには2つのプロパティがあり、どちらも IReadOnlyList<object> 型です。

  • PreviousSelection - 選択が変更される前に選択されていた項目のリスト。
  • CurrentSelection - 選択項目の変更後、選択されている項目のリスト。

さらに、CollectionView には、選択した項目の一覧でSelectedItems プロパティを更新する UpdateSelectedItems メソッドがありますが、変更通知を 1 つだけ発行します。

単一選択

SelectionMode プロパティが Single に設定されている場合は、CollectionView の 1 つの項目を選択できます。 項目が選択されると、SelectedItem プロパティは選択された項目の値に設定されます。 このプロパティが変更されると、SelectionChangedCommand が実行され (SelectionChangedCommandParameter の値が ICommand に渡されます)、SelectionChanged イベントが発生します。

次の XAML の例は、単一項目の選択に応答する CollectionView を示しています:

<CollectionView ItemsSource="{Binding Monkeys}"
                SelectionMode="Single"
                SelectionChanged="OnCollectionViewSelectionChanged">
    ...
</CollectionView>

同等の C# コードを次に示します。

CollectionView collectionView = new CollectionView
{
    SelectionMode = SelectionMode.Single
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
collectionView.SelectionChanged += OnCollectionViewSelectionChanged;

このコード例では、SelectionChanged イベントが発生すると、OnCollectionViewSelectionChanged イベント ハンドラーが実行され、そのイベント ハンドラーは以前に選択した項目と現在選択されている項目を取得します:

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

重要

SelectionChanged イベントは、 SelectionMode プロパティを変更した結果として起こる変化によって発生する場合があります。

次のスクリーンショットは、CollectionView での単一の項目の選択を示しています。

iOS および Android での、1 つ選択された CollectionView のバーティカル リストのスクリーンショット

複数選択

SelectionMode プロパティが Multiple に設定されている場合は、 CollectionView 内の複数の項目を選択できます。 項目が選ばれると、SelectedItems プロパティが選択された項目に設定されます。 このプロパティが変更されると、SelectionChangedCommand が実行され (SelectionChangedCommandParameter の値が ICommand に渡されます)、SelectionChanged イベントが発生します。

次の XAML の例は、複数の項目の選択に応答できる CollectionView を示しています:

<CollectionView ItemsSource="{Binding Monkeys}"
                SelectionMode="Multiple"
                SelectionChanged="OnCollectionViewSelectionChanged">
    ...
</CollectionView>

同等の C# コードを次に示します。

CollectionView collectionView = new CollectionView
{
    SelectionMode = SelectionMode.Multiple
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
collectionView.SelectionChanged += OnCollectionViewSelectionChanged;

このコード例では、OnCollectionViewSelectionChanged イベント ハンドラーは、SelectionChanged イベントが発生したときに実行され、イベント ハンドラーは以前に選択した項目と現在選択されている項目を取得します。

void OnCollectionViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var previous = e.PreviousSelection;
    var current = e.CurrentSelection;
    ...
}

重要

SelectionChanged イベントは、 SelectionMode プロパティを変更した結果として起こる変化によって発生する場合があります。

次のスクリーンショットは、CollectionView での複数の項目の選択を示しています。

iOS と Android で複数選択されている CollectionView バーティカル リストのスクリーンショット

単一の事前選択

SelectionMode プロパティが Single に設定されている場合、SelectedItem プロパティを項目に設定することで、CollectionView 内の単一の項目を事前選択できます。 次の XAML 例は、単一の項目を事前選択する CollectionView を示しています。

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

同等の C# コードを次に示します。

CollectionView collectionView = new CollectionView
{
    SelectionMode = SelectionMode.Single
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
collectionView.SetBinding(SelectableItemsView.SelectedItemProperty, "SelectedMonkey");

Note

SelectedItem プロパティの既定のバインド モードは TwoWay です。

SelectedItem プロパティ データは、Monkey 型の接続ビュー モデルの SelectedMonkey プロパティにバインドされます。 既定では、TwoWay バインドが使われるため、ユーザーが選択されている項目を変更すると、SelectedMonkey プロパティの値が、選択された Monkey オブジェクトに設定されます。 SelectedMonkey プロパティは MonkeysViewModel クラスで定義され、Monkeys コレクションの 4 番目の項目に設定されます。

public class MonkeysViewModel : INotifyPropertyChanged
{
    ...
    public ObservableCollection<Monkey> Monkeys { get; private set; }

    Monkey selectedMonkey;
    public Monkey SelectedMonkey
    {
        get
        {
            return selectedMonkey;
        }
        set
        {
            if (selectedMonkey != value)
            {
                selectedMonkey = value;
            }
        }
    }

    public MonkeysViewModel()
    {
        ...
        selectedMonkey = Monkeys.Skip(3).FirstOrDefault();
    }
    ...
}

そのため、CollectionView が表示されると、一覧の 4 番目の項目が事前選択されます。

iOS および Android での、1 つ事前選択された CollectionView のバーティカル リストのスクリーンショット

複数の事前選択

SelectionMode プロパティが Multiple に設定されている場合、CollectionView 内の複数の項目を事前選択できます。 次の XAML 例は、複数の項目の事前選択を有効にする CollectionView を示しています。

<CollectionView x:Name="collectionView"
                ItemsSource="{Binding Monkeys}"
                SelectionMode="Multiple"
                SelectedItems="{Binding SelectedMonkeys}">
    ...
</CollectionView>

同等の C# コードを次に示します。

CollectionView collectionView = new CollectionView
{
    SelectionMode = SelectionMode.Multiple
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
collectionView.SetBinding(SelectableItemsView.SelectedItemsProperty, "SelectedMonkeys");

Note

SelectedItems プロパティの既定のバインド モードは OneWay です。

SelectedItems プロパティ データは、ObservableCollection<object> 型の接続ビュー モデルの SelectedMonkeys プロパティにバインドされます。 SelectedMonkeys プロパティは、MonkeysViewModel クラスで定義され、Monkeys コレクション内の 2 番目、4 番目、5 番目の項目に設定されます。

namespace CollectionViewDemos.ViewModels
{
    public class MonkeysViewModel : INotifyPropertyChanged
    {
        ...
        ObservableCollection<object> selectedMonkeys;
        public ObservableCollection<object> SelectedMonkeys
        {
            get
            {
                return selectedMonkeys;
            }
            set
            {
                if (selectedMonkeys != value)
                {
                    selectedMonkeys = value;
                }
            }
        }

        public MonkeysViewModel()
        {
            ...
            SelectedMonkeys = new ObservableCollection<object>()
            {
                Monkeys[1], Monkeys[3], Monkeys[4]
            };
        }
        ...
    }
}

そのため、CollectionView が表示されると、一覧の 2 番目、4 番目、5 番目の項目が事前選択されます。

iOS と Android で複数事前選択された CollectionView バーティカル リストのスクリーンショット

選択解除

SelectedItem プロパティと SelectedItems プロパティは、それら、またはそれらがバインドするオブジェクトを null に設定することで選択解除できます。

選択した項目の色を変更する

CollectionView には、CollectionView で選択した項目に対する視覚的な変更を開始するために使用できる Selected VisualState があります。 この VisualState の一般的なユース ケースは、選択した項目の背景色を変更することです。これは、次の XAML の例に示します。

<ContentPage ...>
    <ContentPage.Resources>
        <Style TargetType="Grid">
            <Setter Property="VisualStateManager.VisualStateGroups">
                <VisualStateGroupList>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal" />
                        <VisualState x:Name="Selected">
                            <VisualState.Setters>
                                <Setter Property="BackgroundColor"
                                        Value="LightSkyBlue" />
                            </VisualState.Setters>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateGroupList>
            </Setter>
        </Style>
    </ContentPage.Resources>
    <StackLayout Margin="20">
        <CollectionView ItemsSource="{Binding Monkeys}"
                        SelectionMode="Single">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Grid Padding="10">
                        ...
                    </Grid>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </StackLayout>
</ContentPage>

重要

Selected VisualState を含む Style には、DataTemplate のルート要素の型である TargetTypeプロパティ値が必要です。これは、ItemTemplate プロパティ値として設定されます。

この例では、ItemTemplate のルート要素が Grid であるため、Style.TargetType プロパティの値は Grid に設定されます。 Selected VisualStateは、CollectionView内の項目を選択すると、項目のBackgroundColorLightSkyBlueに設定されることを指定します。

iOS および Android において、カスタムで 1 つの色が選択された CollectionView バーティカル リストのスクリーンショット

ビジュアルの状態の詳細については、「Xamarin.Forms Visual State Manager」をご覧ください。

選択を無効にする

CollectionView 選択は既定では無効になっています。 ただし、CollectionView で選択が有効になっている場合は、SelectionMode プロパティを None に設定することで無効にすることができます。

<CollectionView ...
                SelectionMode="None" />

同等の C# コードを次に示します。

CollectionView collectionView = new CollectionView
{
    ...
    SelectionMode = SelectionMode.None
};

SelectionMode プロパティが None に設定されている場合、CollectionView 内の項目は選択できず、SelectedItem プロパティは null のままになり、SelectionChanged イベントは発生しません。

Note

項目が選択され、SelectionMode プロパティが Single から None に変更されると、SelectedItem プロパティが null に設定され、SelectionChanged イベントは空の CurrentSelection プロパティで発生します。