Vinculação de dados com tipos incompatíveis
- {númeroDeMinutos} minutos
Às vezes, os dados que você está usando não correspondem ao tipo de dados da propriedade de controle que exibe os dados. Por exemplo, você pode ter um valor monetário armazenado em um decimal tipo que deseja exibir em um Label controle, formatado como uma moeda. Um exemplo mais complicado seria com o aplicativo de clima apresentado no módulo. Uma imagem deve ser exibida com base no valor de enumeração da previsão do tempo Sunny ou Cloudy, mas não é possível vincular o valor de enumeração da fonte à propriedade da imagem de um destino. Esta unidade analisa formas de converter dados.
Formatação de cadeia de caracteres
Uma incompatibilidade de tipo comum ocorre quando um tipo intrínseco precisa ser apresentado como uma string formatada. Como quando você deseja exibir partes de um DateTime valor ou formatar um decimal tipo como moeda.
Suponha que você queira exibir o valor devido em uma fatura e tenha essa propriedade em seu objeto de dados:
public decimal BillAmount { get; set; }
O valor devido acaba sendo de 22.0304. Você pode usar dois controles de rótulo para exibir algum texto e o valor em dólar, conforme demonstrado no trecho a seguir:
<HorizontalStackLayout>
<Label Text="You owe" Margin="0,0,5,0" />
<Label Text="{Binding BillAmount}" />
<Label Text="to the bank" Margin="5,0,0,0" />
</HorizontalStackLayout>
Isso gera uma string para a UI que se parece com You owe 22.0304 to the bank, mas falta o símbolo de moeda e pode haver muitas ou poucas casas decimais com base na moeda local. Normalmente, você processaria o valor como uma cadeia de caracteres com o especificador de formato "C" (ou moeda) no código, da seguinte forma:
string formattedBillAmount = string.Format("{0:C}", BillAmount);
Mas para usar a formatação na vinculação de dados, você precisa fazer com que o objeto de dados forneça essa cadeia de caracteres formatada para você como uma propriedade diferente, ou intercetá-la de alguma forma e formatá-la você mesmo. Felizmente, as associações MAUI do .NET fornecem uma maneira de formatar cadeias de caracteres com a StringFormat propriedade de vinculação. A cadeia de caracteres de formato segue as mesmas regras que o String.Format método. Coloque a cadeia de caracteres de formato entre aspas simples para que o analisador XAML não seja confundido pelas chaves encaracoladas. O parâmetro de formato de String 0 é o valor da propriedade que os processos de ligação.
<Label Text="{Binding BillAmount, StringFormat='You owe {0:C} to the bank'}" />
Considere o seguinte XAML, que demonstra a exibição de BillAmount de duas maneiras:
<VerticalStackLayout Padding="10">
<HorizontalStackLayout>
<Label Text="You owe" Margin="0,0,5,0" />
<Label Text="{Binding BillAmount}" />
<Label Text="to the bank" Margin="5,0,0,0" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="{Binding BillAmount, StringFormat='You owe {0:C} to the bank'}" />
</HorizontalStackLayout>
</VerticalStackLayout>
A imagem a seguir ilustra o que a saída XAML produz na tela:
O XAML utilizando a propriedade binding StringFormat é mais simples do que o outro XAML, e tem acesso ao poderoso sistema de formatação de strings do .NET.
Conversão de tipo personalizada
A propriedade StringFormat binding é conveniente ao exibir um valor como uma string, mas não quando queres converter algo de outro tipo, como um Color ou Image. Nesses casos, você precisa escrever um código de conversão personalizado.
Suponha que você esteja solicitando que o usuário escolha uma senha e queira usar uma cor na interface do usuário para indicar a força da senha. Existem três níveis de força: fraco, bom, forte. A força é baseada em quantos caracteres estão na senha. Para dar feedback imediato ao usuário sobre a força da senha, você deseja que o Entry plano de fundo do controle que contém a senha seja alterado com base na força. A imagem a seguir demonstra esses três níveis de força: fraco, bom e forte.
Dos três controles de entrada na captura de tela, o primeiro tem quatro caracteres inseridos e apresenta um fundo vermelho. O segundo tem nove caracteres inseridos e apresenta um fundo amarelo. O último controle de entrada tem 15 caracteres e apresenta um fundo azul.
Estes níveis são atribuídos à Strength enumeração:
private enum Strength
{
Weak,
Good,
Strong
}
Um objeto de dados é atribuído à página como BindingContext, que contém a força da senha na propriedade PasswordStrength. À medida que o usuário digita uma senha, a PasswordStrength propriedade é alterada de acordo com o comprimento da senha. Como o objeto de dados contém a PasswordStrength propriedade, você vincula essa propriedade ao BackgroundColor do Entry controle:
<Entry BackgroundColor="{Binding PasswordStrength} ... />
No entanto, há um problema aqui. O PasswordStrength é do tipo Strength enquanto BackgroundColor é um Color. Estes tipos não são compatíveis entre si. O .NET MAUI fornece uma maneira de corrigir esses problemas de incompatibilidade de tipo, a propriedade de Converter da ligação.
Um conversor de vinculação faz exatamente o que seu nome diz, converte entre a origem e o destino da vinculação. Os conversores são implementados através da IValueConverter interface.
Implementar IValueConverter
Você cria sua lógica de conversão em uma classe que implementa a IValueConverter interface. Normalmente, os nomes dessas classes terminam com o nome Converter para deixar claro seu propósito.
A IValueConverter interface define dois métodos:
Convert: Converte da propriedade da origem da vinculação para a propriedade da interface do usuário do destino da vinculação.ConvertBack: Converte da propriedade UI do destino da vinculação de volta para a propriedade da origem da vinculação.Esse método raramente é usado e não é usado neste cenário. A maioria dos conversores lança um
NotSupportedExceptionpara indicar que essa conversão não é suportada.
Aqui está o contrato da interface:
public interface IValueConverter
{
object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture);
object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture);
}
Lembre-se de que o cenário com o qual estamos trabalhando consiste em vincular a propriedade Entry.BackgroundColor à propriedade do objeto de dados PasswordStrength, que é uma enumeração Strength.
<Entry BackgroundColor="{Binding PasswordStrength} ... />
A Strength enumeração precisa ser convertida num Color, então o conversor precisa avaliar qual valor de Strength é fornecido e retornar um diferente Color. O código a seguir demonstra essa conversão:
namespace MyProject.Converters;
class StrengthToColorConverter : IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
return (Strength)value! switch
{
Strength.Weak => Colors.OrangeRed,
Strength.Good => Colors.Yellow,
Strength.Strong => Colors.LightBlue,
_ => Colors.LightBlue
};
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) =>
throw new NotImplementedException();
}
Vamos detalhar este código:
- O
Convertmétodo tem quatro parâmetros. Geralmente, você pode descartar os dois últimos parâmetros, a menos que tenha um motivo específico para usá-los. - O
valueparâmetro contém o valor de entrada. Neste exemplo, é umStrengthvalor de enumeração. - O parâmetro
targetTypeé ignorado, mas pode-se usar este parâmetro para validar que o tipo de propriedade com a qual o conversor está sendo usado é umColor. Isso é omitido neste exemplo para simplificar. - Uma expressão de switch retorna uma cor diferente com base no
Strengthvalor.
Usar o conversor em XAML
Com a classe de conversor criada, você precisa criar uma instância dela e fazer referência a ela na ligação. A maneira padrão de instanciar o conversor é no dicionário de recursos do elemento raiz.
Primeiro, mapeie um namespace XML para o namespace .NET que contém o conversor. No exemplo de código a seguir, o cvt namespace XML mapeia para o MyProject.Converters namespace .NET:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:cvt="clr-namespace:MyProject.Converters"
...
Em seguida, crie uma instância no ContentPage.Resources:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:cvt="clr-namespace:MyProject.Converters"
x:Class="MyProject.PasswordExample">
<ContentPage.Resources>
<cvt:StrengthToColorConverter x:Key="StrengthToColorConverter" />
</ContentPage.Resources>
Agora, uma instância do conversor está no dicionário de recursos com a chave StrengthToColorConverter, que é coincidentemente o mesmo nome do tipo. Essa é uma maneira típica de nomear conversores, pois geralmente você tem apenas um único conversor que reutiliza em todo o XAML. Se você, por algum motivo, necessitasse de várias instâncias de conversor, as chaves teriam que ser diferentes entre elas.
Por último, consulte o conversor na ligação. Como o conversor está num dicionário de recursos, utiliza a extensão de marcação {StaticResource} para referenciá-lo. O conversor é atribuído à Converter propriedade de associação:
<Entry BackgroundColor="{Binding PasswordStrength, Converter={StaticResource StrengthToColorConverter}}" ... />