Propriedades associáveis
As propriedades associáveis da .NET MAUI (Interface do Usuário de Aplicativo Multiplataforma do .NET) estendem a funcionalidade da propriedade CLR (Common Language Runtime) fazendo backup de uma propriedade com um tipo BindableProperty, em vez de com um campo. A finalidade das propriedades associáveis é fornecer um sistema de propriedades que dê suporte à associação de dados, estilos, modelos e valores definidos por meio de relacionamentos pai-filho. Além disso, as propriedades associáveis podem fornecer valores padrão, validação de valores de propriedade e retornos de chamada que monitoram alterações de propriedade.
Em aplicativos .NET MAUI, as propriedades devem ser implementadas como propriedades associáveis para oferecer suporte a um ou mais dos seguintes recursos:
- Atuar como uma propriedade de destino válida para associação de dados. Para obter mais informações sobre propriedades de destino, consulte Associações básicas.
- Definir a propriedade por meio de um estilo.
- Fornecer um valor de propriedade padrão diferente do padrão para o tipo da propriedade.
- Validando o valor da propriedade.
- Monitorar alterações de propriedade.
Exemplos de propriedades associáveis do .NET MAUI incluem Label.Text
, Button.BorderRadius
e StackLayout.Orientation
. Cada propriedade associável tem um campo correspondente public static readonly
do tipo BindableProperty que é exposto na mesma classe e que é o identificador da propriedade associável. Por exemplo, o identificador de propriedade vinculável correspondente para a propriedade Label.Text
é Label.TextProperty
.
Criar uma propriedade associável
O processo para criar uma propriedade associável é o seguinte:
- Crie uma instância de BindableProperty com uma das sobrecargas do método
BindableProperty.Create
. - Defina acessadores de propriedade para a instância BindableProperty.
Todas as instâncias de BindableProperty precisam ser criadas no thread da interface do usuário. Isso significa que somente o código executado no thread da interface do usuário pode obter ou definir o valor de uma propriedade associável. No entanto, as instâncias de BindableProperty podem ser acessadas de outros threads por marshaling para o thread da interface do usuário. Para obter mais informações, confira Executar código no thread da interface do usuário.
Criar uma propriedade
Para criar uma instância de BindableProperty, a classe contendo precisa derivar da classe BindableObject. No entanto, a classe BindableObject é alta na hierarquia de classes, portanto, a maioria das classes usadas para a funcionalidade da interface do usuário dá suporte a propriedades associáveis.
Uma propriedade associável pode ser criada declarando uma propriedade public static readonly
do tipo BindableProperty. A propriedade associável deve ser definida como o valor retornado de uma das sobrecargas do método BindableProperty.Create
. A declaração deve estar dentro do corpo da classe derivada BindableObject, mas fora de quaisquer definições de membro.
No mínimo, um identificador precisa ser especificado ao criar um BindableProperty, juntamente com os seguintes parâmetros:
- O nome do BindableProperty.
- O tipo da propriedade.
- O tipo do objeto proprietário.
- O valor padrão para a propriedade. Isso garante que a propriedade sempre retorne um valor padrão específico quando a definição dela é removida e ele pode ser diferente do valor padrão para o tipo da propriedade. O valor padrão será restaurado quando o método
ClearValue
for chamado na propriedade associável.
Importante
A convenção de nomenclatura para propriedades associáveis é que o identificador de propriedade associável precisa corresponder ao nome da propriedade especificado no método Create
, com "Property" anexado a ele.
O seguinte código mostra um exemplo de uma propriedade associável, com um identificador e valores para os quatro parâmetros necessários:
public static readonly BindableProperty IsExpandedProperty =
BindableProperty.Create ("IsExpanded", typeof(bool), typeof(Expander), false);
Isso cria uma instância de BindableProperty chamada IsExpandedProperty
, do tipo bool
. A propriedade pertence à classe Expander
e tem um valor padrão de false
.
Observação
Expander
é um controle no .NET MAUI Community Toolkit. Para obter mais informações, confira Expander.
Opcionalmente, ao criar uma instância de BindableProperty, os seguintes parâmetros podem ser especificados:
- O modo de associação. Isso é usado para especificar a direção na qual as alterações de valor de propriedade serão propagadas. No modo de associação padrão, as alterações serão propagadas da origem para o destino. Para obter mais informações, confira Associações básicas.
- Um delegado de validação que será chamado quando o valor da propriedade for definido. Para obter mais informações, confira Retornos de chamada de validação.
- Uma propriedade alterou o delegado que será invocado quando o valor da propriedade for alterado. Para obter mais informações, confira Detectar alterações de propriedade.
- Uma propriedade alterando o delegado que será invocado quando o valor da propriedade for alterado. Esse delegado tem a mesma assinatura que o delegado de propriedade alterada.
- Um delegado de imposição de valor que será invocado quando o valor da propriedade for alterado. Para obter mais informações, confira Retornos de chamada de imposição de valor.
- Um
Func
que é usado para inicializar um valor de propriedade padrão. Para obter mais informações, consulte Criar um valor padrão com um Func.
Criar acessadores
Os acessadores de propriedade são obrigados a usar a sintaxe de propriedade para acessar uma propriedade associável. O acessador Get
deve retornar o valor contido na propriedade associável correspondente. Isso pode ser obtido chamando o método GetValue
, passando o identificador de propriedade associável no qual obter o valor e, em seguida, convertendo o resultado para o tipo necessário. O acessador Set
deve definir o valor da propriedade associável correspondente. Isso pode ser obtido chamando o método SetValue
, passando o identificador de propriedade associável no qual definir o valor e o valor a ser definido.
O seguinte exemplo de código mostra os acessadores da propriedade associável IsExpanded
:
public bool IsExpanded
{
get => (bool)GetValue(IsExpandedProperty);
set => SetValue(IsExpandedProperty, value);
}
Consumir uma propriedade associável
Depois que uma propriedade associável é criada, ela pode ser consumida de XAML ou código. Em XAML, isso é obtido declarando um namespace com um prefixo, com a declaração de namespace indicando o nome do namespace do CLR e, opcionalmente, um nome de assembly. Para obter mais informações, confira Namespaces de XAML.
O seguinte exemplo de código demonstra um namespace XAML para um tipo personalizado que contém uma propriedade associável, que é definida dentro do mesmo assembly que o código do aplicativo que está fazendo referência ao tipo personalizado:
<ContentPage ... xmlns:local="clr-namespace:DataBindingDemos" ...>
...
</ContentPage>
A declaração de namespace é usada ao definir a propriedade associável IsExpanded
, conforme demonstrado no seguinte exemplo de código XAML:
<Expander IsExpanded="true">
...
</Expander>
O código C# equivalente é mostrado no exemplo de código a seguir:
Expander expander = new Expander
{
IsExpanded = true
};
Cenários avançados
Ao criar uma instância de BindableProperty, há vários parâmetros opcionais que podem ser definidos para habilitar cenários avançados de propriedade associável. Esta seção explora esses cenários.
Detectar alterações de propriedade
Um método de retorno de chamada static
de propriedade alterada pode ser registrado com uma propriedade associável especificando o parâmetro propertyChanged
para o método BindableProperty.Create
. O método de retorno de chamada especificado será invocado quando o valor da propriedade associável for alterado.
O seguinte exemplo de código mostra como a propriedade associável IsExpanded
registra o método OnIsExpandedChanged
como um método de retorno de chamada de propriedade alterada:
public static readonly BindableProperty IsExpandedProperty =
BindableProperty.Create(nameof(IsExpanded), typeof(bool), typeof(Expander), false, propertyChanged: OnIsExpandedChanged);
...
static void OnIsExpandedChanged (BindableObject bindable, object oldValue, object newValue)
{
// Property changed implementation goes here
}
No método de retorno de chamada de propriedade alterada, o parâmetro BindableObject é usado para indicar qual instância da classe proprietária relatou uma alteração, e os valores dos dois parâmetros object
representam os valores antigos e novos da propriedade associável.
Retornos de chamada de validação
Um método de retorno de chamada de validação static
pode ser registrado com uma propriedade associável especificando o parâmetro validateValue
para o método BindableProperty.Create
. O método de retorno de chamada especificado será invocado quando o valor da propriedade associável for definido.
O seguinte exemplo de código mostra como a propriedade associável Angle
registra o método IsValidValue
como um método de retorno de chamada de validação:
public static readonly BindableProperty AngleProperty =
BindableProperty.Create("Angle", typeof(double), typeof(MainPage), 0.0, validateValue: IsValidValue);
...
static bool IsValidValue(BindableObject view, object value)
{
double result;
double.TryParse(value.ToString(), out result);
return (result >= 0 && result <= 360);
}
Os retornos de chamada de validação são fornecidos com um valor e devem retornar true
se o valor for válido para a propriedade, caso contrário false
. Uma exceção será gerada se um retorno de chamada de validação retornar false
, que você deve tratar. Um uso típico de um método de retorno de chamada de validação é restringir os valores de inteiros ou duplos quando a propriedade associável é definida. Por exemplo, o método IsValidValue
verifica se o valor da propriedade é um double
dentro do intervalo de 0 a 360.
Retornos de chamada de imposição de valor
Um método de retorno de chamada de imposição de valor static
pode ser registrado com uma propriedade associável especificando o parâmetro coerceValue
para o método BindableProperty.Create
. O método de retorno de chamada especificado será chamado quando o valor da propriedade associável estiver prestes a ser alterado, para que você possa ajustar o novo valor antes que ele seja aplicado.
Importante
Além de ser acionado pelo mecanismo de propriedade associável, você pode invocar retornos de chamada de imposição de valor a partir do código. O tipo BindableObject tem um método CoerceValue
que pode ser chamado para forçar uma reavaliação do valor do argumento BindableProperty dele, invocando o retorno de chamada de imposição de valor dele.
Os retornos de chamada de imposição de valor são usados para forçar uma reavaliação de uma propriedade associável quando o valor da propriedade está prestes a mudar. Por exemplo, um retorno de chamada de imposição de valor pode ser usado para garantir que o valor de uma propriedade associável não seja maior do que o valor de outra propriedade associável.
O seguinte exemplo de código mostra como a propriedade associável Angle
registra o método CoerceAngle
como um método de retorno de chamada de imposição de valor:
public static readonly BindableProperty AngleProperty =
BindableProperty.Create("Angle", typeof(double), typeof(MainPage), 0.0, coerceValue: CoerceAngle);
public static readonly BindableProperty MaximumAngleProperty =
BindableProperty.Create("MaximumAngle", typeof(double), typeof(MainPage), 360.0, propertyChanged: ForceCoerceValue);
...
static object CoerceAngle(BindableObject bindable, object value)
{
MainPage page = bindable as MainPage;
double input = (double)value;
if (input > page.MaximumAngle)
{
input = page.MaximumAngle;
}
return input;
}
static void ForceCoerceValue(BindableObject bindable, object oldValue, object newValue)
{
bindable.CoerceValue(AngleProperty);
}
O método CoerceAngle
verifica o valor MaximumAngle
da propriedade e, se o valor da propriedade Angle
for maior que ele, ele forçará o valor para o valor da propriedade MaximumAngle
. Além disso, quando a propriedade MaximumAngle
é alterada, o retorno de chamada de imposição de valor é invocado na propriedade Angle
chamando o método CoerceValue
.
Criar um valor padrão com um Func
Um Func
pode ser usado para inicializar o valor padrão de uma propriedade associável, conforme demonstrado no seguinte exemplo:
public static readonly BindableProperty DateProperty =
BindableProperty.Create ("Date", typeof(DateTime), typeof(MyPage), default(DateTime), BindingMode.TwoWay, defaultValueCreator: bindable => DateTime.Today);
O parâmetro defaultValueCreator
é definido como um Func
que retorna um DateTime
que representa a data de hoje.