CarouselView では、表示するデータがない場合に、ユーザーへのフィードバックを提供するために使用できる次のプロパティを定義します。
EmptyView(object型):ItemsSourceプロパティがnullの場合、またはItemsSourceプロパティで指定されたコレクションがnullまたは空の場合に表示される文字列、バインディング、またはビューです。 既定値はnullです。EmptyViewTemplate(DataTemplate型): 指定されたEmptyViewの書式設定に使用するテンプレートです。 既定値はnullです。
これらのプロパティは BindableProperty オブジェクトによってサポートされています。つまり、プロパティはデータ バインディングのターゲットになることができます。
EmptyView プロパティを設定する主な使用シナリオは、CarouselView でのフィルタリング操作でデータが得られなかった場合や、Web サービスからデータを取得しているときにユーザーにフィードバックを表示することです。
Note
EmptyView プロパティは、必要に応じてインタラクティブ コンテンツを含むビューに設定できます。
データ テンプレートの詳細については、「Xamarin.Forms のデータ テンプレート」を参照してください。
データが使用できない場合に文字列を表示する
EmptyView プロパティは文字列に設定できます。この文字列は、ItemsSource プロパティが null の場合、または ItemsSource プロパティで指定されたコレクションが null または空の場合に表示されます。 次の XAML は、このシナリオの例を示しています。
<CarouselView ItemsSource="{Binding EmptyMonkeys}"
EmptyView="No items to display." />
同等の C# コードを次に示します。
CarouselView carouselView = new CarouselView
{
EmptyView = "No items to display."
};
carouselView.SetBinding(ItemsView.ItemsSourceProperty, "EmptyMonkeys");
その結果、データ バインドされたコレクションは null であるため、EmptyView プロパティ値として設定された文字列が表示されます。
データが使用できない場合にビューを表示する
EmptyView プロパティはビューに設定できます。このビューは、ItemsSource プロパティが null の場合、または ItemsSource プロパティで指定されたコレクションが null または空の場合に表示されます。 単一のビューでも、複数の子ビューを含むビューでも表示できます。 次の XAML の例は、複数の子ビューを含むビューに設定された EmptyView プロパティを示しています。
<StackLayout Margin="20">
<SearchBar SearchCommand="{Binding FilterCommand}"
SearchCommandParameter="{Binding Source={RelativeSource Self}, Path=Text}"
Placeholder="Filter" />
<CarouselView ItemsSource="{Binding Monkeys}">
<CarouselView.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>
</CarouselView.EmptyView>
<CarouselView.ItemTemplate>
...
</CarouselView.ItemTemplate>
</CarouselView>
</StackLayout>
この例では、冗長な ContentView のように見えるものが、EmptyView のルート要素として追加されています。 これは、内部では Xamarin.Forms レイアウトのコンテキストを提供しないネイティブ コンテナーに EmptyView が追加されるためです。 したがって、EmptyView を構成するビューを配置するには、ルート レイアウトを追加する必要があります。その子はルート レイアウト内に配置できるレイアウトです。
同等の C# コードを次に示します。
SearchBar searchBar = new SearchBar { ... };
CarouselView carouselView = new CarouselView
{
EmptyView = new ContentView
{
Content = new StackLayout
{
Children =
{
new Label { Text = "No results matched your filter.", ... },
new Label { Text = "Try a broader filter?", ... }
}
}
}
};
carouselView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
SearchBar が FilterCommand を実行すると、CarouselView に表示されるコレクションがフィルタリングされて、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={RelativeSource Self}, Path=Text}"
Placeholder="Filter" />
<CarouselView ItemsSource="{Binding Monkeys}">
<CarouselView.EmptyView>
<controls:FilterData Filter="{Binding Source={x:Reference searchBar}, Path=Text}" />
</CarouselView.EmptyView>
<CarouselView.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>
</CarouselView.EmptyViewTemplate>
<CarouselView.ItemTemplate>
...
</CarouselView.ItemTemplate>
</CarouselView>
</StackLayout>
同等の C# コードを次に示します。
SearchBar searchBar = new SearchBar { ... };
CarouselView carouselView = new CarouselView
{
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 を実行すると、CarouselView によって表示されるコレクションが、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"
xmlns:viewmodels="clr-namespace:CarouselViewDemos.ViewModels"
x:Class="CarouselViewDemos.Views.EmptyViewSwapPage"
Title="EmptyView (swap)">
<ContentPage.BindingContext>
<viewmodels:MonkeysViewModel />
</ContentPage.BindingContext>
<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 SearchCommand="{Binding FilterCommand}"
SearchCommandParameter="{Binding Source={RelativeSource Self}, Path=Text}"
Placeholder="Filter" />
<StackLayout Orientation="Horizontal">
<Label Text="Toggle EmptyViews" />
<Switch Toggled="OnEmptyViewSwitchToggled" />
</StackLayout>
<CarouselView x:Name="carouselView"
ItemsSource="{Binding Monkeys}">
<CarouselView.ItemTemplate>
...
</CarouselView.ItemTemplate>
</CarouselView>
</StackLayout>
</ContentPage>
この XAML は、ページ レベルの ResourceDictionary に 2 つの ContentView オブジェクトを定義し、Switch オブジェクトは、どの ContentView オブジェクトを EmptyView プロパティ値として設定するかを制御します。 Switch が切り替わると、OnEmptyViewSwitchToggled イベント ハンドラーは ToggleEmptyView メソッドを実行します。
void ToggleEmptyView(bool isToggled)
{
carouselView.EmptyView = isToggled ? Resources["BasicEmptyView"] : Resources["AdvancedEmptyView"];
}
ToggleEmptyView メソッドは、Switch.IsToggled プロパティの値に基づいて、carouselView オブジェクトの EmptyView プロパティを、ResourceDictionary に格納されている 2 つの ContentView オブジェクトのいずれかに設定します。 SearchBar が FilterCommand を実行すると、CarouselView に表示されるコレクションがフィルタリングされて、SearchBar.Text プロパティに格納されている検索語句が取得されます。 フィルタリング操作でデータが得られない場合は、EmptyView プロパティとして設定された ContentView オブジェクトが表示されます。
リソース ディクショナリについて詳しくは、「Xamarin.Forms のリソース ディクショナリ」を参照してください。
実行時に EmptyViewTemplate を選択する
CarouselView.EmptyViewTemplate プロパティを DataTemplateSelector オブジェクトに設定することで、EmptyView の外観を、その値に基づいて実行時に選択できます。
<ContentPage ...
xmlns:controls="clr-namespace:CarouselViewDemos.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={RelativeSource Self}, Path=Text}"
Placeholder="Filter" />
<CarouselView ItemsSource="{Binding Monkeys}"
EmptyView="{Binding Source={x:Reference searchBar}, Path=Text}"
EmptyViewTemplate="{StaticResource SearchSelector}">
<CarouselView.ItemTemplate>
...
</CarouselView.ItemTemplate>
</CarouselView>
</StackLayout>
</ContentPage>
同等の C# コードを次に示します。
SearchBar searchBar = new SearchBar { ... };
CarouselView carouselView = new CarouselView()
{
EmptyView = searchBar.Text,
EmptyViewTemplate = new SearchTermDataTemplateSelector { ... }
};
carouselView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
EmptyView プロパティは SearchBar.Text プロパティに設定され、EmptyViewTemplate プロパティは SearchTermDataTemplateSelector オブジェクトに設定されます。
SearchBar が FilterCommand を実行すると、CarouselView に表示されるコレクションがフィルタリングされて、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 の作成」を参照してください。