Układy z możliwością powiązania w programie Xamarin.Forms

Download Sample Pobieranie przykładu

Układy możliwe do powiązania umożliwiają dowolną klasę układu pochodzącą z Layout<T> klasy w celu wygenerowania jej zawartości przez powiązanie z kolekcją elementów z opcją ustawiania wyglądu każdego elementu za pomocą DataTemplateelementu . Układy możliwe do powiązania są dostarczane przez klasę BindableLayout , która uwidacznia następujące dołączone właściwości:

  • ItemsSource — określa kolekcję IEnumerable elementów, które mają być wyświetlane przez układ.
  • ItemTemplate — określa element DataTemplate , który ma być stosowany do każdego elementu w kolekcji elementów wyświetlanych przez układ.
  • ItemTemplateSelector — określa DataTemplateSelector , który będzie używany do wyboru DataTemplate elementu w czasie wykonywania.

Uwaga

Właściwość ma pierwszeństwo ItemTemplate , gdy ItemTemplate właściwości i ItemTemplateSelector są ustawione.

Ponadto BindableLayout klasa uwidacznia następujące właściwości możliwe do powiązania:

  • EmptyView— określa string widok lub, który będzie wyświetlany, gdy ItemsSource właściwość ma wartość , lub gdy kolekcja określona ItemsSource przez właściwość jest nullnull lub jest pusta. Domyślna wartość to null.
  • EmptyViewTemplate — określa DataTemplate , który będzie wyświetlany, gdy ItemsSource właściwość ma nullwartość , lub gdy kolekcja określona przez ItemsSource właściwość jest lub jest null pusta. Domyślna wartość to null.

Uwaga

Właściwość ma pierwszeństwo EmptyViewTemplate , gdy EmptyView właściwości i EmptyViewTemplate są ustawione.

Wszystkie te właściwości można dołączyć do AbsoluteLayoutklas , , FlexLayoutGrid, RelativeLayout, iStackLayout, które pochodzą z Layout<T> klasy .

Klasa Layout<T> uwidacznia Children kolekcję, do której dodawane są elementy podrzędne układu. BindableLayout.ItemsSource Gdy właściwość jest ustawiona na kolekcję elementów i dołączona do Layout<T>klasy pochodnej, każdy element w kolekcji jest dodawany do Layout<T>.Children kolekcji do wyświetlania przez układ. Klasa -pochodna Layout<T>zaktualizuje widoki podrzędne po zmianie bazowej kolekcji. Aby uzyskać więcej informacji na temat Xamarin.Forms cyklu układu, zobacz Tworzenie układu niestandardowego.

Układy możliwe do powiązania powinny być używane tylko wtedy, gdy kolekcja elementów do wyświetlenia jest mała, a przewijanie i zaznaczenie nie jest wymagane. Podczas przewijania można dostarczyć przez zawijanie układu możliwego do powiązania w obiekcie ScrollView, nie jest to zalecane, ponieważ układy możliwe do powiązania nie mają wirtualizacji interfejsu użytkownika. Podczas przewijania jest wymagany widok z możliwością przewijania, który zawiera wirtualizację interfejsu użytkownika, taką jak ListView lub CollectionView, powinien być używany. Brak obserwowania tego zalecenia może prowadzić do problemów z wydajnością.

Ważne

Chociaż technicznie można dołączyć układ możliwy do powiązania z dowolną klasą układu, która pochodzi z Layout<T> klasy, nie zawsze jest to praktyczne, szczególnie w przypadku AbsoluteLayoutklas , Gridi RelativeLayout . Rozważmy na przykład scenariusz wyświetlania kolekcji danych w Grid układzie z możliwością powiązania, w którym każdy element w kolekcji jest obiektem zawierającym wiele właściwości. Każdy wiersz w obiekcie Grid powinien wyświetlać obiekt z kolekcji, z każdą kolumną w Grid wyświetlaniu jednej z właściwości obiektu. DataTemplate Ponieważ obiekt dla układu możliwego do powiązania może zawierać tylko jeden obiekt, jest konieczne, aby ten obiekt był klasą układu zawierającą wiele widoków, które każdy wyświetla jedną z właściwości obiektu w określonej Grid kolumnie. Chociaż ten scenariusz można zrealizować przy użyciu układów możliwych do powiązania, powoduje to, że element nadrzędny Grid zawiera element podrzędny Grid dla każdego elementu w powiązanej kolekcji, co jest wysoce nieefektywnym i problematycznym użyciem Grid układu.

Wypełnianie układu możliwego do powiązania danymi

Układ możliwy do powiązania jest wypełniany danymi, ustawiając jego ItemsSource właściwość na dowolną kolekcję, która implementuje IEnumerableelement , i dołączając go do klasy pochodnej Layout<T>:

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

Równoważny kod języka C# to:

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

BindableLayout.ItemsSource Gdy dołączona właściwość jest ustawiona w układzie, ale BindableLayout.ItemTemplate dołączona właściwość nie jest ustawiona, każdy element w IEnumerable kolekcji będzie wyświetlany przez klasę utworzoną Label przez klasęBindableLayout.

Definiowanie wyglądu elementu

Wygląd każdego elementu w układzie z możliwością powiązania można zdefiniować, ustawiając dołączoną BindableLayout.ItemTemplateDataTemplatewłaściwość na wartość :

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

Równoważny kod języka C# to:

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

W tym przykładzie TopFollowers każdy element w kolekcji będzie wyświetlany przez CircleImage widok zdefiniowany w elemencie DataTemplate:

Bindable layout with a DataTemplate

Aby uzyskać więcej informacji na temat szablonów danych, zobacz Xamarin.Forms Szablony danych.

Wybieranie wyglądu elementu w czasie wykonywania

Wygląd każdego elementu w układzie, który można powiązać, można wybrać w czasie wykonywania na podstawie wartości elementu, ustawiając dołączoną BindableLayout.ItemTemplateSelectorDataTemplateSelectorwłaściwość na wartość :

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

Równoważny kod języka C# to:

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

Użyta DataTemplateSelector w przykładowej aplikacji jest pokazana w poniższym przykładzie:

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

Klasa TechItemTemplateSelector definiuje DefaultTemplate właściwości, XamarinFormsTemplateDataTemplate które są ustawione na różne szablony danych. Metoda OnSelectTemplate zwraca XamarinFormsTemplateelement , który wyświetla element w kolorze ciemnoczerwonym z sercem obok niego, gdy element jest równy "Xamarin.Forms". Gdy element nie jest równy "Xamarin.Forms", OnSelectTemplate metoda zwraca DefaultTemplateelement , który wyświetla element przy użyciu domyślnego koloru elementu Label:

Bindable layout with a DataTemplateSelector

Aby uzyskać więcej informacji na temat selektorów szablonów danych, zobacz Creating a Xamarin.Forms DataTemplateSelector (Tworzenie selektora szablonów danych).

Wyświetlanie ciągu, gdy dane są niedostępne

Właściwość EmptyView można ustawić na ciąg, który będzie wyświetlany przez Label właściwość , gdy ItemsSource właściwość to null, lub gdy kolekcja określona przez ItemsSource właściwość jest lub jest null pusta. Poniższy kod XAML przedstawia przykład tego scenariusza:

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

Wynikiem jest to, że gdy kolekcja powiązana z danymi to null, zostanie wyświetlony ciąg ustawiony jako EmptyView wartość właściwości:

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

Wyświetlanie widoków, gdy dane są niedostępne

Właściwość EmptyView można ustawić na widok, który będzie wyświetlany, gdy ItemsSource właściwość to null, lub gdy kolekcja określona ItemsSource przez właściwość jest lub jest null pusta. Może to być pojedynczy widok lub widok zawierający wiele widoków podrzędnych. Poniższy przykład XAML przedstawia EmptyView właściwość ustawioną na widok zawierający wiele widoków podrzędnych:

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

Wynikiem jest to, że gdy kolekcja powiązana z danymi to null, StackLayout są wyświetlane widoki podrzędne i .

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

EmptyViewTemplate Podobnie można ustawić DataTemplatewłaściwość na , która będzie wyświetlana, gdy ItemsSource właściwość ma nullwartość , lub gdy kolekcja określona przez ItemsSource właściwość jest lub jest null pusta. Obiekt DataTemplate może zawierać jeden widok lub widok zawierający wiele widoków podrzędnych. Ponadto wartość BindingContext elementu EmptyViewTemplate będzie dziedziczona z BindingContext elementu BindableLayout. Poniższy przykład XAML przedstawia EmptyViewTemplate właściwość ustawioną na DataTemplate wartość , która zawiera pojedynczy widok:

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

Wynikiem jest to, że gdy kolekcja powiązana z danymi to null, Label element w pliku DataTemplate jest wyświetlany:

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

Uwaga

Nie EmptyViewTemplate można ustawić właściwości za pomocą elementu DataTemplateSelector.

Wybieranie elementu EmptyView w czasie wykonywania

Widoki, które będą wyświetlane jako EmptyView gdy dane są niedostępne, można zdefiniować jako ContentView obiekty w obiekcie ResourceDictionary. Właściwość EmptyView można następnie ustawić na określoną ContentViewwartość , na podstawie określonej logiki biznesowej w czasie wykonywania. Poniższy kod XAML przedstawia przykład tego scenariusza:

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

Język XAML definiuje dwa ContentView obiekty na poziomie ResourceDictionarystrony, a Switch obiekt kontroluje, który ContentView obiekt zostanie ustawiony jako EmptyView wartość właściwości. Switch Po przełączeniu OnEmptyViewSwitchToggled programu obsługi zdarzeń wykonuje metodę ToggleEmptyView :

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

Metoda ToggleEmptyView ustawia EmptyView właściwość stackLayout obiektu na jeden z dwóch ContentView obiektów przechowywanych w ResourceDictionaryobiekcie na podstawie wartości Switch.IsToggled właściwości . Następnie, gdy kolekcja powiązanych danych to null, ContentView obiekt ustawiony jako właściwość jest wyświetlana EmptyView :

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