BindableLayout
Os layouts associáveis do .NET Multi-Platform App UI (.NET MAUI) permitem que qualquer classe de layout derivada da classe Layout gere seu conteúdo associando-se a uma coleção de itens, com a opção de definir a aparência de cada item com um DataTemplate.
Layouts associáveis são fornecidos pela classe BindableLayout, que expõe as seguintes propriedades anexadas:
ItemsSource
– especifica a coleção de itensIEnumerable
a serem exibidos pelo layout.ItemTemplate
– especifica o DataTemplate a ser aplicado a cada item na coleção de itens exibidos pelo layout.ItemTemplateSelector
– especifica o DataTemplateSelector que será usado para escolher um DataTemplate para um item em tempo de execução.
Observação
A propriedade ItemTemplate
tem precedência quando as propriedades ItemTemplate
e ItemTemplateSelector
estão definidas.
Além disso, a classe BindableLayout expõe as seguintes propriedades associáveis:
EmptyView
– especifica ostring
ou a exibição que será visualizada quando a propriedadeItemsSource
fornull
ou quando a coleção especificada pela propriedadeItemsSource
fornull
ou vazia. O valor padrão énull
.EmptyViewTemplate
– especifica o DataTemplate que será exibido quando a propriedadeItemsSource
fornull
ou quando a coleção especificada pela propriedadeItemsSource
fornull
ou vazia. O valor padrão énull
.
Observação
A propriedade EmptyViewTemplate
tem precedência quando as propriedades EmptyView
e EmptyViewTemplate
estão definidas.
Todas essas propriedades podem ser anexadas às classes AbsoluteLayout, FlexLayout, Grid, HorizontalStackLayout, StackLayout e VerticalStackLayout que derivam da classe Layout.
Quando a propriedade BindableLayout.ItemsSource
é definida como uma coleção de itens e anexada a uma classe derivada do Layout, cada item da coleção é adicionado à classe derivada do Layout para exibição. A classe derivada do Layout atualizará suas exibições filho quando a coleção subjacente for alterada.
Os layouts associáveis só devem ser usados quando a coleção de itens a serem exibidos for pequena, e a rolagem e a seleção não são necessárias. Embora a rolagem possa ser fornecida encapsulando um layout associável em um ScrollView, isso não é recomendado, pois os layouts associáveis não têm virtualização da interface do usuário. Quando a rolagem é necessária, um modo de exibição rolável que inclui a virtualização da interface do usuário, como ListView ou CollectionView, deve ser usado. Não observar essa recomendação pode levar a problemas de desempenho.
Importante
Embora seja tecnicamente possível anexar um layout associável a qualquer classe de layout derivada da classe Layout, nem sempre é prático fazer isso, especialmente para as classes AbsoluteLayout e Grid. Por exemplo, considere o cenário de querer exibir uma coleção de dados em um Grid usando um layout associável, em que cada item da coleção é um objeto que contém várias propriedades. Cada linha no Grid deve exibir um objeto da coleção, com cada coluna no Grid exibindo uma das propriedades do objeto. Como o DataTemplate para o layout associável só pode conter um único objeto, é necessário que esse objeto seja uma classe de layout contendo várias exibições que exibem cada uma das propriedades do objeto em uma coluna Grid específica. Embora esse cenário possa ser realizado com layouts associáveis, ele resulta em um Grid pai que contém um Grid filho para cada item na coleção associada, que é um uso altamente ineficiente e problemático do layout Grid.
Preencher um layout associável com dados
Um layout associável é preenchido com dados definindo sua propriedade ItemsSource
para qualquer coleção que implemente IEnumerable
e anexando-a a uma classe derivada do Layout:
<Grid BindableLayout.ItemsSource="{Binding Items}" />
Este é o código C# equivalente:
IEnumerable<string> items = ...;
Grid grid = new Grid();
BindableLayout.SetItemsSource(grid, items);
Quando a propriedade BindableLayout.ItemsSource
anexada é definida em um layout, mas a propriedade BindableLayout.ItemTemplate
anexada não está definida, cada item da coleção IEnumerable
será exibido por um Label que é criado pela classe BindableLayout.
Definir a aparência do item
A aparência de cada item no layout associável pode ser definida definindo a propriedade BindableLayout.ItemTemplate
anexada como um 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>
Este é o código C# equivalente:
DataTemplate imageTemplate = ...;
StackLayout stackLayout = new StackLayout();
BindableLayout.SetItemsSource(stackLayout, viewModel.User.TopFollowers);
BindableLayout.SetItemTemplate(stackLayout, imageTemplate);
Neste exemplo, cada item da coleção TopFollowers
será exibido por uma exibição Image definida no DataTemplate:
Para obter mais informações sobre modelos de dados, consulte Modelos de dados.
Escolher a aparência do item em tempo de execução
A aparência de cada item no layout associável pode ser escolhida em tempo de execução, com base no valor do item, definindo a propriedade BindableLayout.ItemTemplateSelector
anexada como um DataTemplateSelector:
<FlexLayout BindableLayout.ItemsSource="{Binding User.FavoriteTech}"
BindableLayout.ItemTemplateSelector="{StaticResource TechItemTemplateSelector}"
... />
Este é o código C# equivalente:
DataTemplateSelector dataTemplateSelector = new TechItemTemplateSelector { ... };
FlexLayout flexLayout = new FlexLayout();
BindableLayout.SetItemsSource(flexLayout, viewModel.User.FavoriteTech);
BindableLayout.SetItemTemplateSelector(flexLayout, dataTemplateSelector);
O exemplo a seguir mostra a classe 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;
}
}
A classe TechItemTemplateSelector
define propriedades DefaultTemplate
e MAUITemplate
DataTemplate que são configuradas para diferentes modelos de dados. O método OnSelectTemplate
retorna o MAUITemplate
, que exibe um item em vermelho escuro com um coração ao lado dele, quando o item é igual a ".NET MAUI". Quando o item não é igual a ".NET MAUI", o método OnSelectTemplate
retorna o DefaultTemplate
, que exibe um item usando a cor padrão de um Label:
Para obter mais informações sobre seletores de modelo de dados, consulte Criar um DataTemplateSelector.
Exibir uma cadeia de caracteres quando os dados não estiverem disponíveis
A propriedade EmptyView
pode ser definida como uma cadeia de caracteres, que será exibida por um Label quando a propriedade ItemsSource
for null
ou quando a coleção especificada pela propriedade ItemsSource
for null
ou vazia. O XAML a seguir mostra um exemplo desse cenário:
<StackLayout BindableLayout.ItemsSource="{Binding UserWithoutAchievements.Achievements}"
BindableLayout.EmptyView="No achievements">
...
</StackLayout>
O resultado é que, quando a coleção associada a dados fornull
, a cadeia de caracteres definida como o valor da propriedade EmptyView
é exibida:
Visualizar exibições quando os dados não estiverem disponíveis
A propriedade EmptyView
pode ser definida como um modo de exibição, que será exibido quando a propriedade ItemsSource
for null
ou quando a coleção especificada pela propriedade ItemsSource
fornull
ou vazia. Pode ser uma exibição única ou uma exibição que contém várias exibições filho. O exemplo XAML a seguir mostra a propriedade EmptyView
definida como uma exibição que contém várias exibições filho:
<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>
O resultado é que, quando a coleção associada a dados fornull
, o StackLayout e suas exibições filho são exibidas.
Da mesma forma, o EmptyViewTemplate
pode ser definido como um DataTemplate, que será exibido quando a propriedade ItemsSource
for null
, ou quando a coleção especificada pela propriedade ItemsSource
for null
ou vazia. O DataTemplate pode conter uma única exibição ou uma exibição que contenha várias exibições filho. Além disso, o BindingContext
do EmptyViewTemplate
será herdado do BindingContext
doBindableLayout. O exemplo XAML a seguir mostra a propriedade EmptyViewTemplate
definida como um DataTemplate que contém uma única exibição:
<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>
O resultado é que, quando a coleção associada a dados é null
, o Label no DataTemplate é exibido:
Observação
A propriedade EmptyViewTemplate
não pode ser definida por meio de um DataTemplateSelector.
Escolher um EmptyView em tempo de execução
Exibições que serão exibidas como um EmptyView
quando os dados não estiverem disponíveis podem ser definidas como objetos ContentView em um ResourceDictionary. A propriedade EmptyView
pode ser definida como uma ContentView específica, com base em alguma lógica de negócios, em tempo de execução. O XAML a seguir mostra um exemplo desse cenário:
<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>
O XAML define dois objetos ContentView no ResourceDictionary no nível da página, com o objeto Switch controlando qual objeto ContentView será definido como o valor da propriedade EmptyView
. Quando o Switch é alternado, o manipulador de eventos OnEmptyViewSwitchToggled
executa o método ToggleEmptyView
:
void ToggleEmptyView(bool isToggled)
{
object view = isToggled ? Resources["BasicEmptyView"] : Resources["AdvancedEmptyView"];
BindableLayout.SetEmptyView(stackLayout, view);
}
O método ToggleEmptyView
define a propriedade EmptyView
do objeto StackLayout como um dos dois objetos ContentView armazenados no ResourceDictionary, com base no valor da propriedade Switch.IsToggled
. Em seguida, quando a coleção associada a dados é null
, o objeto ContentView definido como a propriedade EmptyView
é exibido.