Xamarin.Forms CollectionView EmptyView
CollectionView
定义了以下属性,这些属性可用于在没有要显示的数据时提供用户反馈:
EmptyView
,类型为object
,是指当ItemsSource
属性为null
时或当ItemsSource
属性指定的集合为null
或为空时,将显示的字符串、绑定或视图。 默认值为null
。EmptyViewTemplate
,类型为DataTemplate
,用于对指定EmptyView
设置格式的模板。 默认值为null
。
所有这些属性都由 BindableProperty
对象提供支持,这意味着这些属性可以作为数据绑定的目标。
设置 EmptyView
属性的主要使用场景是,在对 CollectionView
执行筛选操作后没有获得数据时显示用户反馈,以及在从 Web 服务检索数据时显示用户反馈。
注意
如果需要,可将 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
的根元素。 这是因为,在内部 EmptyView
会添加到不为 Xamarin.Forms 布局提供任何上下文的一个原生容器。 因此,要定位构成 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
中定义的 Label
(已设置为 EmptyViewTemplate
属性值):
注意
当数据不可用时显示模板化自定义类型时,可将 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
中定义两个 ContentView
对象,其中 Switch
对象控制将哪个 ContentView
对象设置为 EmptyView
属性值。 切换 Switch
时,OnEmptyViewSwitchToggled
事件处理程序会执行 ToggleEmptyView
方法:
void ToggleEmptyView(bool isToggled)
{
collectionView.EmptyView = isToggled ? Resources["BasicEmptyView"] : Resources["AdvancedEmptyView"];
}
ToggleEmptyView
方法根据 Switch.IsToggled
属性的值,将 collectionView
对象的 EmptyView
属性设置为 ResourceDictionary
中存储的两个 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。