Xamarin.Forms EmptyView de CollectionView
CollectionView
define las siguientes propiedades que se pueden usar para proporcionar comentarios de los usuarios cuando no hay datos que mostrar:
EmptyView
, de tipoobject
, la cadena, el enlace o la vista que se mostrarán cuando la propiedadItemsSource
seanull
o cuando la colección especificada por la propiedadItemsSource
seanull
o esté vacía. El valor predeterminado esnull
.EmptyViewTemplate
, de tipoDataTemplate
, la plantilla utilizada para dar formato específico aEmptyView
. El valor predeterminado esnull
.
Todas estas propiedades están respaldadas por objetos BindableProperty
, lo que significa que las propiedades pueden ser destinos de los enlaces de datos.
Los principales escenarios de uso para establecer la propiedad EmptyView
muestran comentarios de usuario cuando una operación de filtrado de un CollectionView
no produce datos y muestra los comentarios de usuario mientras se recuperan datos de un servicio web.
Nota:
La propiedad EmptyView
se puede establecer en una vista que incluya contenido interactivo si es necesario.
Para obtener más información sobre las plantillas de datos, consulte Plantillas de datos de Xamarin.Forms.
Mostrar una cadena cuando los datos no están disponibles
La propiedad EmptyView
se puede establecer en una cadena, que se mostrará cuando la propiedad ItemsSource
sea null
, o cuando la colección especificada por la propiedad ItemsSource
sea null
o esté vacía. En el siguiente XAML se muestra un ejemplo de este caso:
<CollectionView ItemsSource="{Binding EmptyMonkeys}"
EmptyView="No items to display" />
El código de C# equivalente es el siguiente:
CollectionView collectionView = new CollectionView
{
EmptyView = "No items to display"
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "EmptyMonkeys");
El resultado es que, dado que la colección enlazada a datos es null
, se muestra el conjunto de cadenas como el valor de propiedad EmptyView
:
Muestra de vistas cuando los datos no están disponibles
La propiedad EmptyView
se puede establecer en una vista, que se mostrará cuando la propiedad ItemsSource
sea null
, o cuando la colección especificada por la propiedad ItemsSource
sea null
o esté vacía. Puede ser una sola vista o una vista que contenga varias vistas secundarias. En el ejemplo XAML siguiente se muestra la propiedad EmptyView
establecida en una vista que contiene varias vistas secundarias:
<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>
En este ejemplo, lo que parece un ContentView
redundante se ha agregado como el elemento raíz del EmptyView
. Esto se debe a que internamente, el EmptyView
se agrega a un contenedor nativo que no proporciona ningún contexto para el diseño Xamarin.Forms. Por lo tanto, para colocar las vistas que componen EmptyView
, debes agregar un diseño raíz, cuyo elemento secundario es un diseño que puede colocarse dentro del diseño raíz.
El código de C# equivalente es el siguiente:
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");
Cuando SearchBar
ejecuta FilterCommand
, la colección mostrada por CollectionView
se filtra para el término de búsqueda almacenado en la propiedad SearchBar.Text
. Si la operación de filtrado no produce ningún dato, se muestra el conjunto StackLayout
establecido como valor de propiedad EmptyView
:
Mostrar un tipo personalizado con plantilla cuando los datos no están disponibles
La propiedad EmptyView
se puede establecer en un tipo personalizado, cuya plantilla se muestra cuando la propiedad ItemsSource
es null
o cuando la colección especificada por la propiedad ItemsSource
es null
o está vacía. La propiedad EmptyViewTemplate
se puede establecer en un DataTemplate
que define la apariencia de EmptyView
. En el siguiente XAML se muestra un ejemplo de este caso:
<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>
El código de C# equivalente es el siguiente:
SearchBar searchBar = new SearchBar { ... };
CollectionView collectionView = new CollectionView
{
EmptyView = new FilterData { Filter = searchBar.Text },
EmptyViewTemplate = new DataTemplate(() =>
{
return new Label { ... };
})
};
El tipo FilterData
define una propiedad Filter
y una BindableProperty
correspondiente:
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); }
}
}
La propiedad EmptyView
se establece en un objeto FilterData
y los datos de propiedad Filter
se enlazan a la propiedad SearchBar.Text
. Cuando SearchBar
ejecuta FilterCommand
, la colección mostrada por CollectionView
se filtra para el término de búsqueda almacenado en la propiedad Filter
. Si la operación de filtrado no produce ningún dato, se muestra la clase Label
definida en DataTemplate
que se establece como valor de propiedad EmptyViewTemplate
:
Nota:
Al mostrar un tipo personalizado con plantilla cuando los datos no están disponibles, la propiedad EmptyViewTemplate
se puede establecer en una vista que contenga varias vistas secundarias.
Elección de EmptyView en tiempo de ejecución
Las vistas que se mostrarán como EmptyView
cuando los datos no estén disponibles, se pueden definir como objetos ContentView
en un ResourceDictionary
. Luego, la propiedad EmptyView
se puede establecer en un elemento ContentView
específico, en función de alguna lógica de negocios, en tiempo de ejecución. En el siguiente archivo XAML se muestra un ejemplo de este escenario:
<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>
Este XAML define dos objetos ContentView
en el nivel de página ResourceDictionary
, con el objeto Switch
que controla qué objeto ContentView
se establecerá como valor de propiedad EmptyView
. Cuando Switch
está activado, el controlador de eventos OnEmptyViewSwitchToggled
ejecuta el método ToggleEmptyView
:
void ToggleEmptyView(bool isToggled)
{
collectionView.EmptyView = isToggled ? Resources["BasicEmptyView"] : Resources["AdvancedEmptyView"];
}
El método ToggleEmptyView
establece la propiedad EmptyView
del objeto collectionView
en uno de los dos objetos ContentView
almacenados en ResourceDictionary
, en función del valor de la propiedad Switch.IsToggled
. Cuando SearchBar
ejecuta FilterCommand
, la colección mostrada por CollectionView
se filtra para el término de búsqueda almacenado en la propiedad SearchBar.Text
. Si la operación de filtrado no produce datos, se muestra el objeto ContentView
establecido como propiedad EmptyView
:
Para más información sobre los diccionarios de recursos, consulte Diccionarios de recursos Xamarin.Forms.
Elección de EmptyViewTemplate en tiempo de ejecución
La apariencia de EmptyView
se puede elegir en tiempo de ejecución, en función de su valor, estableciendo la propiedad CollectionView.EmptyViewTemplate
en un objeto DataTemplateSelector
:
<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>
El código de C# equivalente es el siguiente:
SearchBar searchBar = new SearchBar { ... };
CollectionView collectionView = new CollectionView
{
EmptyView = searchBar.Text,
EmptyViewTemplate = new SearchTermDataTemplateSelector { ... }
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
La propiedad EmptyView
se define en la propiedad SearchBar.Text
y la propiedad EmptyViewTemplate
, en un objeto SearchTermDataTemplateSelector
.
Cuando SearchBar
ejecuta FilterCommand
, la colección mostrada por CollectionView
se filtra para el término de búsqueda almacenado en la propiedad SearchBar.Text
. Si la operación de filtrado no produce ningún dato, la DataTemplate
elegida por el objeto SearchTermDataTemplateSelector
se fija como la propiedad EmptyViewTemplate
y se muestra.
En el ejemplo siguiente se muestra la clase 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;
}
}
La clase SearchTermTemplateSelector
define DefaultTemplate
y OtherTemplate
DataTemplate
propiedades que se establecen en diferentes plantillas de datos. La invalidación OnSelectTemplate
devuelve DefaultTemplate
, que muestra un mensaje al usuario, cuando la consulta de búsqueda no es igual a "xamarin". Cuando la consulta de búsqueda es igual a "xamarin", la invalidación OnSelectTemplate
devuelve OtherTemplate
, que muestra un mensaje básico al usuario:
Para más información sobre los selectores de plantillas de datos, consulte Creación de una instancia de Xamarin.Forms DataTemplateSelector.