Diseños enlazables en Xamarin.Forms

Descargar ejemplo. Descarga del ejemplo

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 de IEnumerable elementos que va a mostrar el diseño.
  • ItemTemplate : especifica que se DataTemplate aplicará a cada elemento de la colección de elementos mostrados por el diseño.
  • ItemTemplateSelector : especifica que se usará para elegir un elemento DataTemplateSelector para un elemento en tiempo de DataTemplate ejecución.

Nota

La ItemTemplate propiedad tiene prioridad cuando se establecen las propiedades y ItemTemplate ItemTemplateSelector .

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 la string propiedad esté o esté ItemsSource null ItemsSource null vacía. El valor predeterminado es null.
  • EmptyViewTemplate : especifica el objeto que se mostrará cuando la propiedad sea o cuando la colección DataTemplate especificada por la propiedad esté o esté ItemsSource null ItemsSource null vacía. El valor predeterminado es null.

Nota

La EmptyViewTemplate propiedad tiene prioridad cuando se establecen las propiedades y EmptyView EmptyViewTemplate .

Todas estas propiedades se pueden adjuntar a las clases AbsoluteLayout , , , y , que se FlexLayout Grid RelativeLayout StackLayout derivan de la clase Layout<T> .

La Layout<T> clase expone una colección, a la que se agregan los elementos secundarios de un Children 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.ItemsSource Layout<T> el Layout<T>.Children diseño. Después, Layout<T> 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 Crear un diseño personalizado.

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 Grid RelativeLayout . 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 Grid Grid Grid 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 IEnumerable Layout<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.ItemsSource BindableLayout.ItemTemplate la IEnumerable Label BindableLayout 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 CircleImage DataTemplate :

Diseño enlazable con una datatemplate.

Para obtener más información sobre las plantillas de datos, consulte Plantillas de datos de Xamarin.Forms.

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 DefaultTemplate XamarinFormsTemplate DataTemplate 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 " XamarinFormsTemplate Xamarin.Forms ". Cuando el elemento no es igual a " ", el método devuelve , que muestra un elemento con el Xamarin.Forms OnSelectTemplate color predeterminado de DefaultTemplate Label :

Diseño enlazable con DataTemplateSelector.

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 EmptyView Label esté ItemsSource null ItemsSource null 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 null valor EmptyView de propiedad:

! [Captura de pantalla de una vista vacía de cadena de diseño enlazable, en iOS y Android] (bindable-layouts-images/emptyview-string.png "Bindable layout string empty view".

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 EmptyView ItemsSource esté o esté null ItemsSource null 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.

! [Captura de pantalla de una vista vacía de diseño enlazable con varias vistas, en iOS y Android] (bindable-layouts-images/emptyview-views.png "Bindable layout empty view".

De forma similar, se puede establecer en , que se mostrará cuando la propiedad sea o cuando la colección especificada por la propiedad EmptyViewTemplate DataTemplate esté o esté ItemsSource null ItemsSource null 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 null Label DataTemplate :

! [Captura de pantalla de una plantilla de vista vacía de diseño enlazable, en iOS y Android] (bindable-layouts-images/emptyviewtemplate.png "Bindable layout empty view template".

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 ContentView ResourceDictionary . 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 ResourceDictionary Switch ContentView establecerá como valor de EmptyView propiedad. Cuando se Switch alterna , el controlador de eventos ejecuta el método OnEmptyViewSwitchToggled ToggleEmptyView :

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 ToggleEmptyView , en función del valor de la propiedad EmptyView stackLayout ContentView ResourceDictionary Switch.IsToggled . A continuación, cuando la colección enlazada a datos es , se muestra el objeto establecido como null ContentView la propiedad EmptyView :

! [Captura de pantalla de la opción de vista vacía en tiempo de ejecución, en iOS y Android] (bindable-layouts-images/emptyview-runtime.png "Bindable layout empty view runtime choice".