Xamarin.Forms CollectionView EmptyView
CollectionView
では、表示するデータがない場合に、ユーザーへのフィードバックを提供するために使用できる次のプロパティを定義します。
EmptyView
(object
型):ItemsSource
プロパティがnull
の場合、またはItemsSource
プロパティで指定されたコレクションがnull
または空の場合に表示される文字列、バインディング、またはビューです。 既定値はnull
です。EmptyViewTemplate
(DataTemplate
型): 指定されたEmptyView
の書式設定に使用するテンプレートです。 既定値はnull
です。
これらのプロパティは BindableProperty
オブジェクトによってサポートされています。つまり、プロパティはデータ バインディングのターゲットになることができます。
EmptyView
プロパティを設定する主な使用シナリオは、CollectionView
でのフィルタリング操作でデータが得られなかった場合や、Web サービスからデータを取得しているときにユーザーにフィードバックを表示することです。
Note
EmptyView
プロパティは、必要に応じてインタラクティブ コンテンツを含むビューに設定できます。
データ テンプレートの詳細については、「Xamarin.Forms のデータ テンプレート」を参照してください。
データが使用できない場合に文字列を表示する
EmptyView
プロパティは文字列に設定できます。この文字列は、ItemsSource
プロパティが null
の場合、または ItemsSource
プロパティで指定されたコレクションが null
または空の場合に表示されます。 次の XAML は、このシナリオの例を示しています。
<CollectionView ItemsSource="{Binding EmptyMonkeys}"
EmptyView="No items to display" />
同等の C# コードを次に示します。
CollectionView collectionView = new CollectionView
{
EmptyView = "No items to display"
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "EmptyMonkeys");
その結果、データ バインドされたコレクションが null
であるため、EmptyView
プロパティ値として設定された文字列が表示されます。
データが使用できない場合にビューを表示する
EmptyView
プロパティはビューに設定できます。このビューは、ItemsSource
プロパティが null
の場合、または ItemsSource
プロパティで指定されたコレクションが null
または空の場合に表示されます。 単一のビューでも、複数の子ビューを含むビューでも表示できます。 次の XAML の例は、複数の子ビューを含むビューに設定された EmptyView
プロパティを示しています。
<StackLayout Margin="20">
<SearchBar x:Name="searchBar"
SearchCommand="{Binding FilterCommand}"
SearchCommandParameter="{Binding Source={x:Reference searchBar}, Path=Text}"
Placeholder="Filter" />
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemTemplate>
<DataTemplate>
...
</DataTemplate>
</CollectionView.ItemTemplate>
<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>
</CollectionView>
</StackLayout>
この例では、冗長な ContentView
のように見えるものが、EmptyView
のルート要素として追加されています。 これは、内部では Xamarin.Forms レイアウトのコンテキストを提供しないネイティブ コンテナーに EmptyView
が追加されるためです。 したがって、EmptyView
を構成するビューを配置するには、ルート レイアウトを追加する必要があります。その子はルート レイアウト内に配置できるレイアウトです。
同等の C# コードを次に示します。
SearchBar searchBar = new SearchBar { ... };
CollectionView collectionView = new CollectionView
{
EmptyView = new ContentView
{
Content = new StackLayout
{
Children =
{
new Label { Text = "No results matched your filter.", ... },
new Label { Text = "Try a broader filter?", ... }
}
}
}
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
SearchBar
が FilterCommand
を実行すると、CollectionView
によって表示されるコレクションが、SearchBar.Text
プロパティに格納されている検索語でフィルター処理されます。 フィルタリング操作でデータが得られない場合は、EmptyView
プロパティ値として設定された StackLayout
が表示されます。
データが使用できない場合にテンプレート化されたカスタム型を表示する
EmptyView
プロパティはカスタム型に設定できます。そのテンプレートは、ItemsSource
プロパティが null
の場合、または ItemsSource
プロパティで指定されたコレクションが null
または空の場合に表示されます。 EmptyViewTemplate
プロパティは、EmptyView
の外観を定義する DataTemplate
に設定できます。 次の XAML は、このシナリオの例を示しています。
<StackLayout Margin="20">
<SearchBar x:Name="searchBar"
SearchCommand="{Binding FilterCommand}"
SearchCommandParameter="{Binding Source={x:Reference searchBar}, Path=Text}"
Placeholder="Filter" />
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemTemplate>
<DataTemplate>
...
</DataTemplate>
</CollectionView.ItemTemplate>
<CollectionView.EmptyView>
<views:FilterData Filter="{Binding Source={x:Reference searchBar}, Path=Text}" />
</CollectionView.EmptyView>
<CollectionView.EmptyViewTemplate>
<DataTemplate>
<Label Text="{Binding Filter, StringFormat='Your filter term of {0} did not match any records.'}"
Margin="10,25,10,10"
FontAttributes="Bold"
FontSize="18"
HorizontalOptions="Fill"
HorizontalTextAlignment="Center" />
</DataTemplate>
</CollectionView.EmptyViewTemplate>
</CollectionView>
</StackLayout>
同等の C# コードを次に示します。
SearchBar searchBar = new SearchBar { ... };
CollectionView collectionView = new CollectionView
{
EmptyView = new FilterData { Filter = searchBar.Text },
EmptyViewTemplate = new DataTemplate(() =>
{
return new Label { ... };
})
};
FilterData
型は、Filter
プロパティと、対応する BindableProperty
を定義します。
public class FilterData : BindableObject
{
public static readonly BindableProperty FilterProperty = BindableProperty.Create(nameof(Filter), typeof(string), typeof(FilterData), null);
public string Filter
{
get { return (string)GetValue(FilterProperty); }
set { SetValue(FilterProperty, value); }
}
}
EmptyView
プロパティは FilterData
オブジェクトに設定され、Filter
プロパティ データは SearchBar.Text
プロパティにバインドされます。 SearchBar
が FilterCommand
を実行すると、CollectionView
で表示されるコレクションが、Filter
プロパティに格納されている検索語でフィルター処理されます。 フィルタリング操作でデータが得られない場合は、DataTemplate
で定義され、EmptyViewTemplate
プロパティ値として設定されている Label
が表示されます。
Note
データを使用できないときにテンプレート化されたカスタム型を表示する場合、EmptyViewTemplate
プロパティを複数の子ビューを含むビューに設定できます。
実行時に EmptyView を選択する
データを使用できない場合に EmptyView
として表示されるビューは、ResourceDictionary
内の ContentView
オブジェクトとして定義できます。 EmptyView
プロパティは、実行時にビジネス ロジックに基づいて特定の ContentView
に設定できます。 次の XAML は、このシナリオの例を示しています。
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CollectionViewDemos.Views.EmptyViewSwapPage"
Title="EmptyView (swap)">
<ContentPage.Resources>
<ContentView x:Key="BasicEmptyView">
<StackLayout>
<Label Text="No items to display."
Margin="10,25,10,10"
FontAttributes="Bold"
FontSize="18"
HorizontalOptions="Fill"
HorizontalTextAlignment="Center" />
</StackLayout>
</ContentView>
<ContentView x:Key="AdvancedEmptyView">
<StackLayout>
<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>
</ContentPage.Resources>
<StackLayout Margin="20">
<SearchBar x:Name="searchBar"
SearchCommand="{Binding FilterCommand}"
SearchCommandParameter="{Binding Source={x:Reference searchBar}, Path=Text}"
Placeholder="Filter" />
<StackLayout Orientation="Horizontal">
<Label Text="Toggle EmptyViews" />
<Switch Toggled="OnEmptyViewSwitchToggled" />
</StackLayout>
<CollectionView x:Name="collectionView"
ItemsSource="{Binding Monkeys}">
<CollectionView.ItemTemplate>
<DataTemplate>
...
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage>
この XAML は、ページ レベルの ResourceDictionary
に 2 つの ContentView
オブジェクトを定義します。Switch
オブジェクトは、どの ContentView
オブジェクトを EmptyView
プロパティ値として設定するかを制御します。 Switch
が切り替わると、OnEmptyViewSwitchToggled
イベント ハンドラーは ToggleEmptyView
メソッドを実行します。
void ToggleEmptyView(bool isToggled)
{
collectionView.EmptyView = isToggled ? Resources["BasicEmptyView"] : Resources["AdvancedEmptyView"];
}
ToggleEmptyView
メソッドは、Switch.IsToggled
プロパティの値に基づいて、collectionView
オブジェクトの EmptyView
プロパティを、ResourceDictionary
に格納されている 2 つの ContentView
オブジェクトのいずれかに設定します。 SearchBar
が FilterCommand
を実行すると、CollectionView
で表示されるコレクションが、SearchBar.Text
プロパティに格納されている検索語でフィルター処理されます。 フィルタリング操作でデータが得られない場合は、EmptyView
プロパティとして設定された ContentView
オブジェクトが表示されます。
リソース ディクショナリについて詳しくは、「Xamarin.Forms のリソース ディクショナリ」を参照してください。
実行時に EmptyViewTemplate を選択する
CollectionView.EmptyViewTemplate
プロパティを DataTemplateSelector
オブジェクトに設定することで、EmptyView
の外観を、その値に基づいて実行時に選択できます。
<ContentPage ...
xmlns:controls="clr-namespace:CollectionViewDemos.Controls">
<ContentPage.Resources>
<DataTemplate x:Key="AdvancedTemplate">
...
</DataTemplate>
<DataTemplate x:Key="BasicTemplate">
...
</DataTemplate>
<controls:SearchTermDataTemplateSelector x:Key="SearchSelector"
DefaultTemplate="{StaticResource AdvancedTemplate}"
OtherTemplate="{StaticResource BasicTemplate}" />
</ContentPage.Resources>
<StackLayout Margin="20">
<SearchBar x:Name="searchBar"
SearchCommand="{Binding FilterCommand}"
SearchCommandParameter="{Binding Source={x:Reference searchBar}, Path=Text}"
Placeholder="Filter" />
<CollectionView ItemsSource="{Binding Monkeys}"
EmptyView="{Binding Source={x:Reference searchBar}, Path=Text}"
EmptyViewTemplate="{StaticResource SearchSelector}" />
</StackLayout>
</ContentPage>
同等の C# コードを次に示します。
SearchBar searchBar = new SearchBar { ... };
CollectionView collectionView = new CollectionView
{
EmptyView = searchBar.Text,
EmptyViewTemplate = new SearchTermDataTemplateSelector { ... }
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
EmptyView
プロパティは SearchBar.Text
プロパティに設定され、EmptyViewTemplate
プロパティは SearchTermDataTemplateSelector
オブジェクトに設定されます。
SearchBar
が FilterCommand
を実行すると、CollectionView
に表示されるコレクションがフィルタリングされて、SearchBar.Text
プロパティに格納されている検索語句が取得されます。 フィルタリング操作でデータが得られない場合は、SearchTermDataTemplateSelector
オブジェクトで選択された DataTemplate
が EmptyViewTemplate
プロパティとして設定され、表示されます。
次の例は、SearchTermDataTemplateSelector
クラスを示しています。
public class SearchTermDataTemplateSelector : DataTemplateSelector
{
public DataTemplate DefaultTemplate { get; set; }
public DataTemplate OtherTemplate { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
string query = (string)item;
return query.ToLower().Equals("xamarin") ? OtherTemplate : DefaultTemplate;
}
}
SearchTermTemplateSelector
クラスは、異なるデータ テンプレートに設定される DefaultTemplate
および OtherTemplate
DataTemplate
プロパティを定義します。 検索クエリが "xamarin" と等しくない場合、OnSelectTemplate
オーバーライドは DefaultTemplate
を返し、ユーザーにメッセージが表示されます。 検索クエリが "xamarin" と等しい場合、OnSelectTemplate
オーバーライドは OtherTemplate
を返し、ユーザーに基本的なメッセージが表示されます。
データ テンプレート セレクターについて詳しくは、「Xamarin.Forms DataTemplateSelector の作成」を参照してください。