Diseños enlazables en Xamarin.Forms
Los diseños enlazables permiten que cualquier clase de diseño que se derive de la clase genere su contenido enlazando a una colección de elementos, con la opción de establecer la apariencia de cada elemento con Layout<T>DataTemplate . La clase proporciona diseños BindableLayout enlazables, que expone las siguientes propiedades adjuntas:
ItemsSource: especifica la colección deIEnumerableelementos que va a mostrar el diseño.ItemTemplate: especifica que seDataTemplateaplicará a cada elemento de la colección de elementos mostrados por el diseño.ItemTemplateSelector: especifica que se usará para elegir un elementoDataTemplateSelectorpara un elemento en tiempo deDataTemplateejecución.
Nota:
La ItemTemplate propiedad tiene prioridad cuando se establecen las propiedades y ItemTemplateItemTemplateSelector .
Además, la BindableLayout clase expone las siguientes propiedades enlazables:
EmptyView: especifica la vista o que se mostrará cuando la propiedad sea o cuando la colección especificada por lastringpropiedad esté o estéItemsSourcenullItemsSourcenullvacía. El valor predeterminado esnull.EmptyViewTemplate: especifica el objeto que se mostrará cuando la propiedad sea o cuando la colecciónDataTemplateespecificada por la propiedad esté o estéItemsSourcenullItemsSourcenullvacía. El valor predeterminado esnull.
Nota:
La EmptyViewTemplate propiedad tiene prioridad cuando se establecen las propiedades y EmptyViewEmptyViewTemplate .
Todas estas propiedades se pueden adjuntar a las clases , , , y , que se AbsoluteLayoutFlexLayoutGridRelativeLayoutStackLayout derivan de la Layout<T> clase .
La Layout<T> clase expone una colección Xamarin_Forms Layout<T> _Layout_1_Children" data-linktype="absolute-path">, a la que se agregan los elementos secundarios Children de un diseño. Cuando la propiedad se establece en una colección de elementos y se adjunta a una clase derivada de , cada elemento de la colección se agrega a la colección para que lo muestre BinableLayout.ItemsSourceLayout<T> el Layout<T>.Children diseño. A Layout<T> continuación, la clase derivada de actualizará sus vistas secundarias cuando cambie la colección subyacente. Para obtener más información sobre el ciclo Xamarin.Forms de diseño, vea Xamarin.Forms.
Los diseños enlazables solo se deben usar cuando la colección de elementos que se va a mostrar es pequeña y no es necesario desplazarse y seleccionar. Aunque el desplazamiento se puede proporcionar encapsulando un diseño enlazable en , no se recomienda, ya que los diseños enlazables carecen de ScrollView virtualización de la interfaz de usuario. Cuando se requiere el desplazamiento, se debe usar una vista desplazable que incluya virtualización de la interfaz de usuario, como ListView o CollectionView . Si no se observa esta recomendación, se pueden producir problemas de rendimiento.
Importante
Aunque técnicamente es posible asociar un diseño enlazable a cualquier clase de diseño que derive de la clase , no siempre es práctico hacerlo, especialmente para las clases Layout<T>AbsoluteLayout , y GridRelativeLayout . Por ejemplo, considere el escenario de querer mostrar una colección de datos en mediante un diseño enlazable, donde cada elemento de la colección es un objeto que contiene Grid varias propiedades. Cada fila de debe mostrar un objeto de la colección, y cada columna de debe mostrar Grid una de las propiedades del Grid objeto. Dado que para el diseño enlazable solo puede contener un solo objeto, es necesario que ese objeto sea una clase de diseño que contenga varias vistas que muestren cada una de las propiedades del objeto en una DataTemplate columna Grid específica. Aunque este escenario se puede convertir en diseños enlazables, da como resultado un elemento primario que contiene un elemento secundario para cada elemento de la colección enlazada, que es un uso altamente ineficaz y problemático del GridGridGrid diseño.
Rellenar un diseño enlazable con datos
Un diseño enlazable se rellena con datos estableciendo su propiedad en cualquier colección que implemente y asociándose ItemsSource a una clase derivada de IEnumerableLayout<T> :
<Grid BindableLayout.ItemsSource="{Binding Items}" />
El código de C# equivalente es el siguiente:
IEnumerable<string> items = ...;
var grid = new Grid();
BindableLayout.SetItemsSource(grid, items);
Cuando la propiedad adjunta se establece en un diseño, pero la propiedad adjunta no está establecida, la clase que crea mostrará todos los elementos de BindableLayout.ItemsSourceBindableLayout.ItemTemplate la IEnumerableLabelBindableLayout colección.
Definición de la apariencia del elemento
La apariencia de cada elemento en el diseño enlazable se puede definir estableciendo la BindableLayout.ItemTemplate propiedad adjunta en DataTemplate :
<StackLayout BindableLayout.ItemsSource="{Binding User.TopFollowers}"
Orientation="Horizontal"
...>
<BindableLayout.ItemTemplate>
<DataTemplate>
<controls:CircleImage Source="{Binding}"
Aspect="AspectFill"
WidthRequest="44"
HeightRequest="44"
... />
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
El código de C# equivalente es el siguiente:
DataTemplate circleImageTemplate = ...;
var stackLayout = new StackLayout();
BindableLayout.SetItemsSource(stackLayout, viewModel.User.TopFollowers);
BindableLayout.SetItemTemplate(stackLayout, circleImageTemplate);
En este ejemplo, cada elemento de la TopFollowers colección se mostrará mediante una vista definida en CircleImageDataTemplate :

Para obtener más información sobre las plantillas de datos, vea Xamarin.Forms Data Templates .
Elección de la apariencia del elemento en tiempo de ejecución
La apariencia de cada elemento del diseño enlazable se puede elegir en tiempo de ejecución, en función del valor del elemento, estableciendo la propiedad BindableLayout.ItemTemplateSelector adjunta en DataTemplateSelector :
<FlexLayout BindableLayout.ItemsSource="{Binding User.FavoriteTech}"
BindableLayout.ItemTemplateSelector="{StaticResource TechItemTemplateSelector}"
... />
El código de C# equivalente es el siguiente:
DataTemplateSelector dataTemplateSelector = new TechItemTemplateSelector { ... };
var flexLayout = new FlexLayout();
BindableLayout.SetItemsSource(flexLayout, viewModel.User.FavoriteTech);
BindableLayout.SetItemTemplateSelector(flexLayout, dataTemplateSelector);
El DataTemplateSelector utilizado en la aplicación de ejemplo se muestra en el ejemplo siguiente:
public class TechItemTemplateSelector : DataTemplateSelector
{
public DataTemplate DefaultTemplate { get; set; }
public DataTemplate XamarinFormsTemplate { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
return (string)item == "Xamarin.Forms" ? XamarinFormsTemplate : DefaultTemplate;
}
}
La TechItemTemplateSelector clase define las propiedades y que se establecen en plantillas de datos DefaultTemplateXamarinFormsTemplateDataTemplate diferentes. El método devuelve , que muestra un elemento en rojo oscuro con un corazón junto a él, cuando el OnSelectTemplate elemento es igual a " XamarinFormsTemplateXamarin.Forms ". Cuando el elemento no es igual a " ", el método devuelve , que muestra un elemento con el Xamarin.FormsOnSelectTemplate color predeterminado de DefaultTemplateLabel :

Para obtener más información sobre los selectores de plantillas de datos, vea Creating a Xamarin.Forms DataTemplateSelector .
Mostrar una cadena cuando los datos no están disponibles
La propiedad se puede establecer en una cadena, que se mostrará mediante cuando la propiedad sea , o cuando la colección especificada por la propiedad esté o EmptyViewLabel esté ItemsSourcenullItemsSourcenull vacía. El código XAML siguiente muestra un ejemplo de este escenario:
<StackLayout BindableLayout.ItemsSource="{Binding UserWithoutAchievements.Achievements}"
BindableLayout.EmptyView="No achievements">
...
</StackLayout>
El resultado es que, cuando la colección enlazada a datos es , se muestra la cadena establecida como nullEmptyView valor de propiedad:
Mostrar vistas cuando los datos no están disponibles
La propiedad se puede establecer en una vista, que se mostrará cuando la propiedad sea , o cuando la colección especificada por la propiedad EmptyViewItemsSource esté o esté nullItemsSourcenull vacía. Puede ser una vista única o una vista que contenga varias vistas secundarias. En el ejemplo xaml siguiente se muestra EmptyView la propiedad establecida en una vista que contiene varias vistas secundarias:
<StackLayout BindableLayout.ItemsSource="{Binding UserWithoutAchievements.Achievements}">
<BindableLayout.EmptyView>
<StackLayout>
<Label Text="None."
FontAttributes="Italic"
FontSize="{StaticResource smallTextSize}" />
<Label Text="Try harder and return later?"
FontAttributes="Italic"
FontSize="{StaticResource smallTextSize}" />
</StackLayout>
</BindableLayout.EmptyView>
...
</StackLayout>
El resultado es que cuando la colección enlazada a datos null es , se muestran y sus vistas StackLayout secundarias.
De forma similar, se puede establecer en , que se mostrará cuando la propiedad sea , o cuando la colección especificada por la propiedad EmptyViewTemplateDataTemplate esté o esté ItemsSourcenullItemsSourcenull vacía. puede DataTemplate contener una sola vista o una vista que contiene varias vistas secundarias. Además, el BindingContext de EmptyViewTemplate se heredará de BindingContext de BindableLayout . En el ejemplo xaml siguiente se muestra EmptyViewTemplate la propiedad establecida en que contiene una sola DataTemplate vista:
<StackLayout BindableLayout.ItemsSource="{Binding UserWithoutAchievements.Achievements}">
<BindableLayout.EmptyViewTemplate>
<DataTemplate>
<Label Text="{Binding Source={x:Reference usernameLabel}, Path=Text, StringFormat='{0} has no achievements.'}" />
</DataTemplate>
</BindableLayout.EmptyViewTemplate>
...
</StackLayout>
El resultado es que cuando la colección enlazada a datos es , se muestra en nullLabelDataTemplate :
Nota:
La EmptyViewTemplate propiedad no se puede establecer a través de DataTemplateSelector .
Elegir una vista vacía en tiempo de ejecución
Las vistas que se mostrarán como cuando los datos no estén disponibles, se pueden EmptyView definir como objetos en ContentViewResourceDictionary . A EmptyView continuación, la propiedad se puede establecer en un ContentView específico, en función de alguna lógica de negocios, en tiempo de ejecución. El código XAML siguiente muestra un ejemplo de este escenario:
<ContentPage ...>
<ContentPage.Resources>
...
<ContentView x:Key="BasicEmptyView">
<StackLayout>
<Label Text="No achievements."
FontSize="14" />
</StackLayout>
</ContentView>
<ContentView x:Key="AdvancedEmptyView">
<StackLayout>
<Label Text="None."
FontAttributes="Italic"
FontSize="14" />
<Label Text="Try harder and return later?"
FontAttributes="Italic"
FontSize="14" />
</StackLayout>
</ContentView>
</ContentPage.Resources>
<StackLayout>
...
<Switch Toggled="OnEmptyViewSwitchToggled" />
<StackLayout x:Name="stackLayout"
BindableLayout.ItemsSource="{Binding UserWithoutAchievements.Achievements}">
...
</StackLayout>
</StackLayout>
</ContentPage>
Xaml define dos objetos en el nivel de página , con el objeto ContentView que controla qué objeto se ResourceDictionarySwitchContentView establecerá como valor de EmptyView propiedad. Cuando se Switch alterna , el controlador de eventos ejecuta el método OnEmptyViewSwitchToggledToggleEmptyView :
void ToggleEmptyView(bool isToggled)
{
object view = isToggled ? Resources["BasicEmptyView"] : Resources["AdvancedEmptyView"];
BindableLayout.SetEmptyView(stackLayout, view);
}
El método establece la propiedad del objeto en uno de los dos objetos almacenados en , en función del valor de la propiedad ToggleEmptyViewEmptyView Xamarin_Forms stackLayoutContentViewResourceDictionaryToggleEmptyView _Switch_IsToggled" data-linktype="absolute-path">. Switch.IsToggled A continuación, cuando la colección enlazada a datos es , se muestra el objeto establecido como nullContentView la propiedad EmptyView :
Descarga del ejemplo
en la vista vacía de cadena de diseño enlazable dey Android
en una plantilla de vista vacía de diseño enlazable dey Android
opción de tiempo de ejecución