Layout associabili in Xamarin.Forms

Download Sample Scaricare l'esempio

I layout associabili consentono a qualsiasi classe di layout che deriva dalla Layout<T> classe di generare il contenuto associandolo a una raccolta di elementi, con l'opzione per impostare l'aspetto di ogni elemento con un oggetto DataTemplate. I layout associabili vengono forniti dalla BindableLayout classe , che espone le proprietà associate seguenti:

  • ItemsSource : specifica la raccolta di IEnumerable elementi da visualizzare nel layout.
  • ItemTemplate : specifica l'oggetto DataTemplate da applicare a ogni elemento nella raccolta di elementi visualizzati dal layout.
  • ItemTemplateSelector : specifica l'oggetto DataTemplateSelector che verrà usato per scegliere un DataTemplate elemento in fase di esecuzione.

Nota

La ItemTemplate proprietà ha la precedenza quando vengono impostate entrambe le ItemTemplate proprietà e ItemTemplateSelector .

Inoltre, la BindableLayout classe espone le proprietà associabili seguenti:

  • EmptyView: specifica la string visualizzazione o che verrà visualizzata quando la proprietà è nullo quando la ItemsSource raccolta specificata dalla ItemsSource proprietà è null o vuota. Il valore predefinito è null.
  • EmptyViewTemplate: specifica l'oggetto DataTemplate che verrà visualizzato quando la proprietà è nullo quando la ItemsSource raccolta specificata dalla ItemsSource proprietà è null o vuota. Il valore predefinito è null.

Nota

La EmptyViewTemplate proprietà ha la precedenza quando vengono impostate entrambe le EmptyView proprietà e EmptyViewTemplate .

Tutte queste proprietà possono essere associate alle AbsoluteLayoutclassi , FlexLayout, GridRelativeLayout, e StackLayout , che derivano tutte dalla Layout<T> classe .

La Layout<T> classe espone una Children raccolta a cui vengono aggiunti gli elementi figlio di un layout. Quando la BindableLayout.ItemsSource proprietà è impostata su una raccolta di elementi e associata a una Layout<T>classe derivata da , ogni elemento dell'insieme viene aggiunto alla raccolta per la Layout<T>.Children visualizzazione dal layout. La Layout<T>classe derivata da aggiornerà quindi le visualizzazioni figlio quando cambia la raccolta sottostante. Per altre informazioni sul ciclo di Xamarin.Forms layout, vedere Creazione di un layout personalizzato.

I layout associabili devono essere usati solo quando la raccolta di elementi da visualizzare è ridotta e lo scorrimento e la selezione non sono necessari. Anche se lo scorrimento può essere fornito eseguendo il wrapping di un layout associabile in un oggetto ScrollView, non è consigliabile perché i layout associabili non dispongono della virtualizzazione dell'interfaccia utente. Quando è necessario lo scorrimento, deve essere usata una visualizzazione scorrevole che include la virtualizzazione dell'interfaccia utente, ad esempio ListView o CollectionView. L'impossibilità di osservare questa raccomandazione può causare problemi di prestazioni.

Importante

Sebbene sia tecnicamente possibile associare un layout associabile a qualsiasi classe di layout che deriva dalla Layout<T> classe , non è sempre pratico farlo, in particolare per le AbsoluteLayoutclassi , Gride RelativeLayout . Si consideri, ad esempio, lo scenario di voler visualizzare una raccolta di dati in un Grid oggetto usando un layout associabile, in cui ogni elemento della raccolta è un oggetto contenente più proprietà. Ogni riga in Grid deve visualizzare un oggetto dall'insieme, con ogni colonna nella Grid visualizzazione di una delle proprietà dell'oggetto. Poiché per DataTemplate il layout associabile può contenere solo un singolo oggetto, è necessario che tale oggetto sia una classe di layout contenente più visualizzazioni che visualizzano ognuna delle proprietà dell'oggetto in una colonna specifica Grid . Sebbene questo scenario possa essere realizzato con layout associabili, viene generato un elemento padre Grid contenente un elemento figlio Grid per ogni elemento nella raccolta associata, che rappresenta un uso estremamente inefficiente e problematico del Grid layout.

Popolare un layout associabile con i dati

Un layout associabile viene popolato con i dati impostando la relativa ItemsSource proprietà su qualsiasi raccolta che implementa IEnumerablee associandola a una Layout<T>classe derivata da :

<Grid BindableLayout.ItemsSource="{Binding Items}" />

Il codice C# equivalente è il seguente:

IEnumerable<string> items = ...;
var grid = new Grid();
BindableLayout.SetItemsSource(grid, items);

Quando la BindableLayout.ItemsSource proprietà associata è impostata su un layout, ma la BindableLayout.ItemTemplate proprietà associata non è impostata, ogni elemento dell'insieme IEnumerable verrà visualizzato da un Label oggetto creato dalla BindableLayout classe .

Definire l'aspetto dell'elemento

L'aspetto di ogni elemento nel layout associabile può essere definito impostando la BindableLayout.ItemTemplate proprietà associata su :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>

Il codice C# equivalente è il seguente:

DataTemplate circleImageTemplate = ...;
var stackLayout = new StackLayout();
BindableLayout.SetItemsSource(stackLayout, viewModel.User.TopFollowers);
BindableLayout.SetItemTemplate(stackLayout, circleImageTemplate);

In questo esempio, ogni elemento dell'insieme TopFollowers verrà visualizzato da una CircleImage visualizzazione definita in DataTemplate:

Bindable layout with a DataTemplate

Per altre informazioni sui modelli di dati, vedere Xamarin.Forms Modelli di dati.

Scegliere l'aspetto dell'elemento in fase di esecuzione

L'aspetto di ogni elemento nel layout associabile può essere scelto in fase di esecuzione, in base al valore dell'elemento, impostando la BindableLayout.ItemTemplateSelector proprietà associata su :DataTemplateSelector

<FlexLayout BindableLayout.ItemsSource="{Binding User.FavoriteTech}"
            BindableLayout.ItemTemplateSelector="{StaticResource TechItemTemplateSelector}"
            ... />

Il codice C# equivalente è il seguente:

DataTemplateSelector dataTemplateSelector = new TechItemTemplateSelector { ... };
var flexLayout = new FlexLayout();
BindableLayout.SetItemsSource(flexLayout, viewModel.User.FavoriteTech);
BindableLayout.SetItemTemplateSelector(flexLayout, dataTemplateSelector);

L'oggetto DataTemplateSelector usato nell'applicazione di esempio è illustrato nell'esempio seguente:

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 classe definisce DefaultTemplate e XamarinFormsTemplateDataTemplate proprietà impostate su modelli di dati diversi. Il OnSelectTemplate metodo restituisce , XamarinFormsTemplateche visualizza un elemento in rosso scuro con un cuore accanto a esso, quando l'elemento è uguale a "Xamarin.Forms". Quando l'elemento non è uguale a "Xamarin.Forms", il OnSelectTemplate metodo restituisce , DefaultTemplateche visualizza un elemento usando il colore predefinito di un oggetto Label:

Bindable layout with a DataTemplateSelector

Per altre informazioni sui selettori di modelli di dati, vedere Creazione di un Xamarin.Forms dataTemplateSelector.

Visualizzare una stringa quando i dati non sono disponibili

La EmptyView proprietà può essere impostata su una stringa, che verrà visualizzata da un Label oggetto quando la proprietà è nullo quando l'insieme ItemsSourceItemsSource specificato dalla proprietà è null o vuoto. Il codice XAML seguente illustra un esempio di questo scenario:

<StackLayout BindableLayout.ItemsSource="{Binding UserWithoutAchievements.Achievements}"
             BindableLayout.EmptyView="No achievements">
    ...
</StackLayout>

Il risultato è che quando la raccolta associata a dati è null, viene visualizzata la stringa impostata come valore della EmptyView proprietà:

Screenshot of a bindable layout string empty view, on iOS and Android

Visualizzare le visualizzazioni quando i dati non sono disponibili

La EmptyView proprietà può essere impostata su una visualizzazione, che verrà visualizzata quando la proprietà è nullo quando l'insieme ItemsSourceItemsSource specificato dalla proprietà è null o vuoto. Può trattarsi di una singola visualizzazione o di una visualizzazione che contiene più visualizzazioni figlio. L'esempio XAML seguente mostra la EmptyView proprietà impostata su una visualizzazione che contiene più visualizzazioni figlio:

<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>

Il risultato è che quando la raccolta associata a dati è null, vengono visualizzate le StackLayout viste figlio e .

Screenshot of a bindable layout empty view with multiple views, on iOS and Android

Analogamente, EmptyViewTemplate può essere impostato su un DataTemplateoggetto , che verrà visualizzato quando la proprietà è nullo quando l'insieme ItemsSource specificato dalla ItemsSource proprietà è null o vuoto. DataTemplate può contenere una singola visualizzazione o una vista che contiene più visualizzazioni figlio. Inoltre, l'oggetto BindingContextEmptyViewTemplate di verrà ereditato dall'oggetto BindingContextBindableLayoutdi . L'esempio XAML seguente mostra la EmptyViewTemplate proprietà impostata su un DataTemplate oggetto contenente una singola visualizzazione:

<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>

Il risultato è che quando la raccolta associata a dati è null, viene visualizzato l'oggetto LabelDataTemplate in :

Screenshot of a bindable layout empty view template, on iOS and Android

Nota

La EmptyViewTemplate proprietà non può essere impostata tramite .DataTemplateSelector

Scegliere un controllo EmptyView in fase di esecuzione

Le viste che verranno visualizzate come un EmptyView oggetto quando i dati non sono disponibili, possono essere definite come ContentView oggetti in un oggetto ResourceDictionary. La EmptyView proprietà può quindi essere impostata su un oggetto specifico ContentView, in base a una logica di business in fase di esecuzione. Il codice XAML seguente illustra un esempio di questo scenario:

<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>

Il codice XAML definisce due ContentView oggetti a livello ResourceDictionarydi pagina, con l'oggetto che controlla l'oggetto SwitchContentView che verrà impostato come valore della EmptyView proprietà. Quando l'oggetto Switch viene attivato o disattivato, il OnEmptyViewSwitchToggled gestore eventi esegue il ToggleEmptyView metodo :

void ToggleEmptyView(bool isToggled)
{
    object view = isToggled ? Resources["BasicEmptyView"] : Resources["AdvancedEmptyView"];
    BindableLayout.SetEmptyView(stackLayout, view);
}

Il ToggleEmptyView metodo imposta la EmptyView proprietà dell'oggetto stackLayout su uno dei due ContentView oggetti archiviati in ResourceDictionary, in base al valore della Switch.IsToggled proprietà . Quindi, quando la raccolta associata a dati è null, viene visualizzato il ContentView set di oggetti come EmptyView proprietà :

Screenshot of empty view choice at runtime, on iOS and Android