Поделиться через


BindableLayout

Просмотрите пример. Обзор примера

Привязываемые макеты многоплатформенного пользовательского интерфейса приложений .NET (.NET MAUI) позволяют любому классу макета, производным от Layout класса, создавать его содержимое путем привязки к коллекции элементов, с параметром задать внешний вид каждого элемента.DataTemplate

Привязываемые макеты предоставляются классом BindableLayout , который предоставляет следующие присоединенные свойства:

  • ItemsSource — указывает коллекцию элементов, отображаемых IEnumerable макетом.
  • ItemTemplate — задает DataTemplate применение к каждому элементу в коллекции элементов, отображаемых макетом.
  • ItemTemplateSelector — указывает DataTemplateSelector , что будет использоваться для выбора DataTemplate элемента во время выполнения.

Примечание.

Свойство ItemTemplate имеет приоритет, если заданы оба ItemTemplate ItemTemplateSelector свойства.

Кроме того, BindableLayout класс предоставляет следующие привязываемые свойства:

  • EmptyView — указывает string или представление, которое будет отображаться, если ItemsSource свойство равно nullили когда коллекция, указанная ItemsSource свойством null , или пуста. Значение по умолчанию — null.
  • EmptyViewTemplate — задает DataTemplate значение, которое будет отображаться, если ItemsSource свойство равно nullили когда коллекция, указанная ItemsSource свойством, или null пуста. Значение по умолчанию — null.

Примечание.

Свойство EmptyViewTemplate имеет приоритет, если заданы оба EmptyView EmptyViewTemplate свойства.

Все эти свойства могут быть присоединены к AbsoluteLayoutклассам , FlexLayout, HorizontalStackLayoutGridи StackLayoutVerticalStackLayout классам, производным Layout от класса.

BindableLayout.ItemsSource Если свойству присвоено значение коллекции элементов и присоединено к Layoutпроизводному классу, каждый элемент в коллекции добавляется в Layoutпроизводный класс для отображения. Затем производный Layoutкласс обновляет дочерние представления при изменении базовой коллекции.

Привязываемые макеты следует использовать только в том случае, если коллекция элементов для отображения невелика, а прокрутка и выделение не требуются. Хотя прокрутка может быть предоставлена путем упаковки привязываемого макета в a ScrollView, это не рекомендуется, так как привязываемые макеты не имеют виртуализации пользовательского интерфейса. Если требуется прокрутка, необходимо использовать прокручиваемое представление, включающее виртуализацию пользовательского интерфейса, например ListView или CollectionView. Сбой в наблюдении за этой рекомендацией может привести к проблемам с производительностью.

Внимание

Хотя технически можно подключить привязываемый макет к любому классу макета, наследуемому AbsoluteLayout от Layout класса, это не всегда удобно сделать, особенно для классов и Grid классов. Например, рассмотрим сценарий отображения коллекции данных в Grid привязываемом макете, где каждый элемент в коллекции является объектом, содержащим несколько свойств. Каждая строка в Grid коллекции должна отображать объект из коллекции с каждым столбцом в Grid отображении одного из свойств объекта. DataTemplate Так как для привязываемого макета может содержаться только один объект, это необходимо для того, чтобы этот объект был классом макета, содержащим несколько представлений, каждый из которых отображает одно из свойств объекта в определенном Grid столбце. Хотя этот сценарий можно реализовать с привязываемыми макетами, он приводит к Grid родительскому элементу, содержашему дочерний Grid элемент в связанной коллекции, что является очень неэффективным и проблемным использованием макета Grid .

Заполнение привязываемого макета данными

Привязываемый макет заполняется данными, задав его ItemsSource свойство любой коллекции, реализующей IEnumerableи присоединяя ее к производном классу Layout:

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

Эквивалентный код на C# выглядит так:

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

BindableLayout.ItemsSource Если присоединенное свойство задано в макете, но BindableLayout.ItemTemplate присоединенное свойство не задано, каждый элемент в IEnumerable коллекции будет отображаться Label классом, созданным классомBindableLayout.

Определение внешнего вида элемента

Внешний вид каждого элемента в привязываемом макете можно определить, задав BindableLayout.ItemTemplate присоединенное свойство следующим DataTemplateобразом:

<StackLayout BindableLayout.ItemsSource="{Binding User.TopFollowers}"
             Orientation="Horizontal"
             ...>
    <BindableLayout.ItemTemplate>
        <DataTemplate>
            <Image Source="{Binding}"
                   Aspect="AspectFill"
                   WidthRequest="44"
                   HeightRequest="44"
                   ... />
        </DataTemplate>
    </BindableLayout.ItemTemplate>
</StackLayout>

Эквивалентный код на C# выглядит так:

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

В этом примере каждый элемент в TopFollowers коллекции будет отображаться представлениемImage, определенным в :DataTemplate

Привязываемый макет .NET MAUI с dataTemplate.

Дополнительные сведения о шаблонах данных см. в разделе "Шаблоны данных".

Выбор внешнего вида элемента во время выполнения

Внешний вид каждого элемента в привязываемом макете можно выбрать во время выполнения на основе значения элемента, задав BindableLayout.ItemTemplateSelector присоединенное свойство следующим DataTemplateSelectorобразом:

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

Эквивалентный код на C# выглядит так:

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

В следующем примере показан TechItemTemplateSelector класс:

public class TechItemTemplateSelector : DataTemplateSelector
{
    public DataTemplate DefaultTemplate { get; set; }
    public DataTemplate MAUITemplate { get; set; }

    protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
    {
        return (string)item == ".NET MAUI" ? MAUITemplate : DefaultTemplate;
    }
}

Класс TechItemTemplateSelector определяет DefaultTemplate и MAUITemplate DataTemplate свойства, которые задаются различными шаблонами данных. Метод OnSelectTemplate возвращает MAUITemplateэлемент, который отображает элемент в темно-красном цвете с сердцем рядом с ним, когда элемент равен .NET MAUI. Если элемент не равен .NET MAUI", OnSelectTemplate метод возвращает DefaultTemplateобъект, который отображает элемент с использованием цвета по умолчанию:Label

Привязываемый макет .NET MAUI с dataTemplateSelector.

Дополнительные сведения о селекторах шаблонов данных см. в разделе "Создание объекта DataTemplateSelector".

Отображение строки при недоступности данных

Свойство EmptyView может быть задано строкой, которая будет отображаться Label в случае, если ItemsSource свойство имеет nullзначение, или когда коллекция, указанная ItemsSource свойством null , или пуста. В следующем коде XAML показан пример этого сценария:

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

Результатом является то, что при сборе nullпривязанных к данным строке EmptyView отображается значение свойства:

Снимок экрана: пустое представление строки привязываемого макета.

Отображение представлений при недоступности данных

Свойство EmptyView может быть задано в представлении, которое будет отображаться, если ItemsSource свойство равно nullили когда коллекция, указанная ItemsSource свойством null , или пуста. Это может быть одно представление или представление, содержащее несколько дочерних представлений. В следующем примере XAML показано EmptyView свойство, заданное для представления, содержащего несколько дочерних представлений:

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

Результатом является то, что при отображении коллекции nullStackLayout привязанных к данным представлений и его дочерних представлений.

Снимок экрана: пустое представление привязываемого макета с несколькими представлениями.

Аналогичным образом EmptyViewTemplate можно задать DataTemplateзначение , которое будет отображаться, если ItemsSource свойство равно nullили когда коллекция, указанная ItemsSource свойством, или null пуста. Может DataTemplate содержать одно представление или представление, содержащее несколько дочерних представлений. Кроме того, BindingContext EmptyViewTemplate наследуется от BindingContext объекта BindableLayout. В следующем примере XAML показан набор EmptyViewTemplate свойств, DataTemplate содержащий одно представление:

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

Результатом является то, что при сборе nullLabel DataTemplate привязанных к данным данных отображается в ней:

Снимок экрана: шаблон пустого представления привязываемого макета.

Примечание.

Свойство EmptyViewTemplate не может быть задано через объект DataTemplateSelector.

Выбор EmptyView во время выполнения

Представления, которые будут отображаться как EmptyView недоступные данные, можно определить как ContentView объекты в объекте ResourceDictionary. Затем EmptyView свойство может быть задано на основе определенной ContentViewбизнес-логики во время выполнения. В следующем коде XAML показан пример этого сценария:

<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 определяет два ContentView объекта на уровне ResourceDictionaryстраницы с Switch объектом, определяющим, какой ContentView объект будет задан в качестве EmptyView значения свойства. Switch При переключение OnEmptyViewSwitchToggled обработчик событий выполняет ToggleEmptyView метод:

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

Метод ToggleEmptyView задает EmptyView свойство StackLayout объекта одному из двух ContentView объектов, хранящихся в объекте ResourceDictionary, на основе значения Switch.IsToggled свойства. Затем, когда коллекция nullпривязанных к данным данных, ContentView объект, заданный в качестве EmptyView свойства, отображается.