Usar associações de dados no XAML

Concluído

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 o BindableProperty deve derivar de BindableObject. Todos os controles fornecidos no .NET MAUI derivam de BindableObject e a maioria de suas propriedades são BindableProperties.

O diagrama a seguir ilustra como uma associação é um objeto intermediário entre duas propriedades:

Um diagrama que ilustra uma vinculação como intermediária entre a propriedade de um objeto fonte e a propriedade vinculável de um objeto de destino.

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 chamada Humidity no tipo WeatherService.

    O Path é o primeiro parâmetro sem nome na sintaxe {Binding} e a sintaxe Path= 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:

Uma imagem animada de um controle deslizante sendo arrastado com um mouse. Conforme o controle deslizante se move, um trecho de texto gira para corresponder à posição do controle.

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:

  1. Se a vinculação definir um Source, essa fonte é usada e a busca é interrompida. O Path da associação é aplicado à Source para obtenção de um valor. Se Source não estiver definida, a pesquisa começará por uma origem da associação.

  2. 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 o Path da associação será aplicado ao BindingContext para obter um valor. Se o BindingContext for nulo, a pesquisa continuará.

  3. Esse processo continuará até chegar à raiz do XAML. A pesquisa termina verificando o BindingContext da raiz de um valor não nulo. Se nenhum BindingContext 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.

Verifique seu conhecimento

1.

Qual das afirmações é verdadeira sobre o objeto de origem em uma associação do .NET MAUI?

2.

Qual das afirmações é verdadeira sobre a propriedade de destino em uma associação do .NET MAUI?

3.

Se todas as associações nos controles de um Grid precisarem do mesmo objeto de origem, qual será a estratégia mais segura para definir o objeto de origem apenas uma vez?