Usar associações de dados no XAML
As associações de dados podem ser declaradas no código ou no XAML usando extensões de marcação. Esta unidade discute esse último, pois é a maneira mais comum de criar associações. Há alguns motivos para preferir o XAML. Primeiro, a maioria das pessoas considera as associações como parte do código da interface do usuário, pois as associações obtêm os dados para exibição na interface do usuário. Em segundo lugar, há uma extensão de marcação chamada Binding
que facilita essa tarefa.
O que são associações de dados
Um associação vincula duas propriedades. Uma propriedade está na interface do usuário e a outra está no objeto do modelo de dados. Se o valor de uma das propriedades for alterado, o objeto de associação poderá atualizar a outra. Em outras palavras, as associações são objetos intermediários que sincronizam a interface do usuário e os dados. Usamos os termos origem e destino para identificar os dois objetos envolvidos:
Determinar a fonte: Uma origem pode ser um objeto de qualquer tipo. Na prática, você normalmente usa um objeto de dados como origem. Você precisa identificar a propriedade nesse objeto de origem para participar da associação. Você identificará a propriedade definindo a propriedade
Path
na associação.Destino: O destino é uma propriedade que é implementada usando uma propriedade especial chamada
BindableProperty
. O objeto com oBindableProperty
deve derivar deBindableObject
. Todos os controles fornecidos no .NET MAUI derivam deBindableObject
e a maioria de suas propriedades sãoBindableProperties
.
O diagrama a seguir ilustra como uma associação é um objeto intermediário entre duas propriedades:
Como criar uma associação de dados no XAML
Vamos dar uma olhada em uma associação simples criada em XAML usando a extensão de marcação {Binding}
. Ela está associando a propriedade WeatherService.Humidity
da origem à propriedade Text
do controle de interface do usuário.
<VerticalStackLayout Margin="10">
<VerticalStackLayout.Resources>
<ResourceDictionary>
<services:WeatherService x:Key="myWeatherService" />
</ResourceDictionary>
</VerticalStackLayout.Resources>
<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" />
</VerticalStackLayout>
A origem da associação é:
Uma instância de objeto do tipo
WeatherService
. A instância é referenciada através da extensão XAML{StaticResource ...}
, que aponta para um objeto no dicionário de recursos do layout em pilha.Os pontos
Path
para uma propriedade chamadaHumidity
no tipoWeatherService
.O
Path
é o primeiro parâmetro sem nome na sintaxe{Binding}
e a sintaxePath=
pode ser omitida. Essas duas associações são equivalentes:<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" /> <Label Text="{Binding Humidity, Source={StaticResource myWeatherService}}" />
O destino de associação é:
- O controle
Label
. - A propriedade
Text
do controle.
Quando a interface do usuário é exibida, a extensão XAML {Binding}
cria uma associação entre o WeatherService
e o Label
. A associação lê o valor da propriedade WeatherService.Humidity
na propriedade Label.Text
.
Usar outro controle como origem da associação
Uma característica útil da associação é ser capaz de associar a outros controles. O XAML a seguir é uma demonstração simples:
<VerticalStackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Label x:Name="TargetLabel" Text="TEXT TO ROTATE" BackgroundColor="Yellow" />
<Slider WidthRequest="100" Maximum="360"
Value="{Binding Rotation, Mode=OneWayToSource, Source={x:Reference TargetLabel}}" />
</VerticalStackLayout>
A propriedade Slider.Value
está associada à propriedade Label.Rotation
, mas de uma maneira diferente da explicada anteriormente. Esta propriedade está utilizando o modo de vinculação OneWayToSource
, que inverte o mecanismo de vinculação típico. Em vez da Origem atualizar o Destino, o OneWayToSource
atualiza a Origem quando o Destino é alterado. Neste exemplo, quando o controle deslizante é movido, ele atualiza a rotação do rótulo com base no valor do controle deslizante, conforme ilustrado na seguinte animação:
O cenário típico para associar controles uns aos outros é quando um controle, geralmente um controle de coleção como um ListView
ou CarouselView
, tem um item selecionado que você deseja usar como origem de dados. No exemplo de uma página exibindo a previsão do tempo, você pode ter um ListView
apresentando a previsão para os próximos cinco dias. Quando o usuário seleciona um dia na lista, os detalhes dessa previsão são exibidos em outros controles. Se o usuário selecionar outro dia, os outros controles serão atualizados novamente com os detalhes do dia selecionado.
Usar a mesma origem entre várias associações
O exemplo anterior demonstrou o uso de um recurso estático como origem para uma única associação. Essa origem pode ser usada em várias associações. Aqui está um exemplo de declaração de uma associação entre três controles diferentes, todos associando ao mesmo objeto e propriedade Path
, embora alguns omitam a propriedade Path
:
<VerticalStackLayout Margin="10">
<VerticalStackLayout.Resources>
<vm:SimpleWeatherServiceObject x:Key="myWeatherService" />
</VerticalStackLayout.Resources>
<Entry Text="{Binding Humidity, Source={StaticResource myWeatherService}}" />
<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" />
</VerticalStackLayout>
Você não precisa usar o mesmo Path
ao usar o mesmo Source
:
<VerticalStackLayout Margin="10">
<VerticalStackLayout.Resources>
<vm:SimpleWeatherServiceObject x:Key="myWeatherService" />
</VerticalStackLayout.Resources>
<Entry Text="{Binding Temperature, Source={StaticResource myWeatherService}}" />
<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" />
</VerticalStackLayout>
Raramente você apresenta uma única parte de dados de uma origem, embora isso possa acontecer. Normalmente, você tem vários controles usando diferentes partes de dados da mesma origem. Essa situação é tão comum que a classe BindableObject
tem uma propriedade chamada BindingContext
que funciona como uma origem para associação de dados. Lembre-se de que os controles do .NET MAUI herdam da classe BindableObject
, portanto, os controles do .NET MAIU têm a propriedade BindingContext
.
É opcional definir a associação Source
. Uma associação que não tem a Source
definida pesquisa automaticamente a árvore visual XAML para um BindingContext
, que é definido no XAML ou atribuído a um elemento pai por código. As associações são avaliadas seguindo este padrão:
Se a vinculação definir um
Source
, essa fonte é usada e a busca é interrompida. OPath
da associação é aplicado àSource
para obtenção de um valor. SeSource
não estiver definida, a pesquisa começará por uma origem da associação.A pesquisa começa com o próprio objeto de destino. Se o objeto de destino
BindingContext
não for nulo, a pesquisa será interrompida e oPath
da associação será aplicado aoBindingContext
para obter um valor. Se oBindingContext
for nulo, a pesquisa continuará.Esse processo continuará até chegar à raiz do XAML. A pesquisa termina verificando o
BindingContext
da raiz de um valor não nulo. Se nenhumBindingContext
válido for encontrado, a associação não terá nada para associar e não fará nada.
É comum definir o BindingContext
no nível do objeto raiz, para aplicá-lo a todo o XAML.
Há um último recurso conveniente que vale a pena mencionar. As associações verificam as alterações na referência de objeto de sua origem. Ele funciona até mesmo para associações que usam BindingContext
como origem. Se a Source
ou o BindingContext
for reatribuído a outro objeto, as associações capturarão os dados da nova origem e atualizarão seu destino.