Vinculação de dados com tipos incompatíveis
À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 da Sunny
previsão do tempo ou Cloudy
da enumeração, mas não é possível vincular o valor de enumeração da origem à propriedade image de um destino. Esta unidade analisa formas de converter dados.
Formatação de cadeia de caracteres
Uma incompatibilidade de tipo comum é um tipo intrínseco que você deseja exibir como uma cadeia de caracteres 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 cadeia de caracteres para a interface do usuário que se parece com You owe 22.0304 to the bank
, mas está faltando 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, assim:
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 como uma propriedade diferente ou intercete-a de alguma forma e formate-a 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 0
String format é o valor da propriedade processado pela ligação.
<Label Text="{Binding BillAmount, StringFormat='You owe {0:C} to the bank'}" />
Considere o seguinte XAML, que demonstra a exibição do uso das BillAmount
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 usando a StringFormat
propriedade binding é mais simples do que o outro XAML, e você tem acesso ao . O poderoso sistema de formatação de cadeias de caracteres da NET.
Conversão de tipo personalizada
A StringFormat
propriedade binding é conveniente ao exibir um valor como uma cadeia de caracteres, mas não quando você deseja converter algo como um Color
ou Image
de outro tipo. 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 como a página , BindingContext
que contém a força da senha com a PasswordStrength
propriedade. À 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 da Converter
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
NotSupportedException
para 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 está vinculando a Entry.BackgroundColor
propriedade à propriedade do objeto de PasswordStrength
dados, que é uma Strength
enumeração.
<Entry BackgroundColor="{Binding PasswordStrength} ... />
A Strength
enumeração precisa ser convertida em um Color
arquivo . Assim, o conversor precisa avaliar qual Strength
valor é 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
Convert
mé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
value
parâmetro contém o valor de entrada. Neste exemplo, é umStrength
valor de enumeração. - O
targetType
parâmetro é ignorado. Mas você pode usar esse parâmetro para validar que o tipo de propriedade com a qual o conversor está sendo usado é umColor
arquivo . Isso é omitido neste exemplo para simplificar. - Uma expressão de switch é usada para retornar uma cor diferente com base no
Strength
valor.
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 passa a ser 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á em um dicionário de recursos, você usa a extensão de {StaticResource}
marcação para fazer referência a ele. O conversor é atribuído à Converter
propriedade de ligação:
<Entry BackgroundColor="{Binding PasswordStrength, Converter={StaticResource StrengthToColorConverter}}" ... />