Xamarin.Forms Propriedades associáveis
As propriedades associáveis estendem a funcionalidade da propriedade CLR fazendo backup de uma propriedade com um BindableProperty
tipo, em vez de fazer backup de uma propriedade 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 relações 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.
As propriedades devem ser implementadas como propriedades associáveis para dar suporte a um ou mais dos seguintes recursos:
- Agindo como uma propriedade de destino válida para associação de dados.
- Definindo a propriedade por meio de um estilo.
- Fornecendo um valor de propriedade padrão diferente do padrão para o tipo da propriedade.
- Validando o valor da propriedade .
- Alterações de propriedade de monitoramento.
Exemplos de Xamarin.Forms propriedades associáveis incluem Label.Text
, Button.BorderRadius
e StackLayout.Orientation
. Cada propriedade associável tem um public static readonly
campo correspondente do tipo BindableProperty
que é exposto na mesma classe e que é o identificador da propriedade associável. Por exemplo, o identificador de propriedade associável correspondente para a Label.Text
propriedade é Label.TextProperty
.
Criar uma propriedade associável
O processo para criar uma propriedade associável é o seguinte:
- Crie uma
BindableProperty
instância com uma das sobrecargas deBindableProperty.Create
método. - Definir acessadores de propriedade para a
BindableProperty
instância.
Todas as BindableProperty
instâncias devem 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, BindableProperty
as instâncias podem ser acessadas de outros threads fazendo marshaling para o thread da interface do usuário com o Device.BeginInvokeOnMainThread
método .
Criar uma propriedade
Para criar uma BindableProperty
instância, a classe que contém deve derivar da BindableObject
classe . No entanto, a BindableObject
classe é alta na hierarquia de classes, portanto, a maioria das classes usadas para a funcionalidade de interface do usuário dá suporte a propriedades associáveis.
Uma propriedade associável pode ser criada declarando uma public static readonly
propriedade do tipo BindableProperty
. A propriedade associável deve ser definida como o valor retornado de uma das sobrecargas do BindableProperty.Create
método. A declaração deve estar dentro do corpo da BindableObject
classe derivada, mas fora de qualquer definição de membro.
No mínimo, um identificador deve 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 não estiver configurada e pode ser diferente do valor padrão para o tipo da propriedade. O valor padrão será restaurado quando o
ClearValue
método for chamado na propriedade associável.
Importante
A convenção de nomenclatura para propriedades associáveis é que o identificador de propriedade associável deve corresponder ao nome da Create
propriedade especificado no método, com "Property" acrescentado a ele.
O código a seguir mostra um exemplo de uma propriedade associável, com um identificador e valores para os quatro parâmetros necessários:
public static readonly BindableProperty EventNameProperty =
BindableProperty.Create ("EventName", typeof(string), typeof(EventToCommandBehavior), null);
Isso cria uma BindableProperty
instância chamada EventNameProperty
, do tipo string
. A propriedade pertence à EventToCommandBehavior
classe e tem um valor padrão de null
.
Opcionalmente, ao criar uma BindableProperty
instância, os seguintes parâmetros podem ser especificados:
- O modo de associação. Isso é usado para especificar a direção na qual as alterações no valor da propriedade serão propagadas. No modo de associação padrão, as alterações serão propagadas da origem para o destino.
- Um delegado de validação que será invocado quando o valor da propriedade for definido. Para obter mais informações, consulte 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, consulte Detectar alterações de propriedade.
- Um delegado de alteração de propriedade que será invocado quando o valor da propriedade for alterado. Esse delegado tem a mesma assinatura que o delegado alterado pela propriedade.
- Um delegado de valor de coerção que será invocado quando o valor da propriedade for alterado. Para obter mais informações, consulte Coagir retornos de chamada 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 necessários para usar a sintaxe de propriedade para acessar uma propriedade associável. O Get
acessador deve retornar o valor contido na propriedade associável correspondente. Isso pode ser obtido chamando o GetValue
método , passando o identificador de propriedade associável no qual obter o valor e, em seguida, convertendo o resultado para o tipo necessário. O Set
acessador deve definir o valor da propriedade associável correspondente. Isso pode ser obtido chamando o SetValue
método , passando o identificador de propriedade associável no qual definir o valor e o valor a ser definido.
O exemplo de código a seguir mostra os acessadores para a EventName
propriedade associável:
public string EventName
{
get { return (string)GetValue (EventNameProperty); }
set { SetValue (EventNameProperty, value); }
}
Consumir uma propriedade associável
Depois que uma propriedade associável for criada, ela poderá ser consumida de XAML ou código. No XAML, isso é obtido declarando um namespace com um prefixo, com a declaração de namespace indicando o nome do namespace CLR e, opcionalmente, um nome de assembly. Para obter mais informações, consulte Namespaces XAML.
O exemplo de código a seguir 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:EventToCommandBehavior" ...>
...
</ContentPage>
A declaração de namespace é usada ao definir a EventName
propriedade associável, conforme demonstrado no seguinte exemplo de código XAML:
<ListView ...>
<ListView.Behaviors>
<local:EventToCommandBehavior EventName="ItemSelected" ... />
</ListView.Behaviors>
</ListView>
O código C# equivalente é mostrado no exemplo de código a seguir:
var listView = new ListView ();
listView.Behaviors.Add (new EventToCommandBehavior
{
EventName = "ItemSelected",
...
});
Cenários avançados
Ao criar uma BindableProperty
instância, 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 static
método de retorno de chamada alterado pela propriedade pode ser registrado com uma propriedade associável especificando o propertyChanged
parâmetro para o BindableProperty.Create
método . O método de retorno de chamada especificado será invocado quando o valor da propriedade associável for alterado.
O exemplo de código a seguir mostra como a EventName
propriedade associável registra o OnEventNameChanged
método como um método de retorno de chamada alterado pela propriedade:
public static readonly BindableProperty EventNameProperty =
BindableProperty.Create (
"EventName", typeof(string), typeof(EventToCommandBehavior), null, propertyChanged: OnEventNameChanged);
...
static void OnEventNameChanged (BindableObject bindable, object oldValue, object newValue)
{
// Property changed implementation goes here
}
No método de retorno de chamada alterado pela propriedade, o BindableObject
parâmetro é usado para indicar qual instância da classe proprietária relatou uma alteração e os valores dos dois object
parâmetros representam os valores antigos e novos da propriedade associável.
Retornos de chamada de validação
Um static
método de retorno de chamada de validação pode ser registrado com uma propriedade associável especificando o validateValue
parâmetro para o BindableProperty.Create
método . O método de retorno de chamada especificado será invocado quando o valor da propriedade associável for definido.
O exemplo de código a seguir mostra como a Angle
propriedade associável registra o IsValidValue
método como um método de retorno de chamada de validação:
public static readonly BindableProperty AngleProperty =
BindableProperty.Create ("Angle", typeof(double), typeof(HomePage), 0.0, validateValue: IsValidValue);
...
static bool IsValidValue (BindableObject view, object value)
{
double result;
bool isDouble = 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 deve ser tratado pelo desenvolvedor. 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 IsValidValue
método verifica se o valor da propriedade é um double
dentro do intervalo de 0 a 360.
Coagir retornos de chamada de valor
Um static
método de retorno de chamada de valor de coerção pode ser registrado com uma propriedade associável especificando o coerceValue
parâmetro para o BindableProperty.Create
método . O método de retorno de chamada especificado será invocado quando o valor da propriedade associável for alterado.
Importante
O BindableObject
tipo tem um CoerceValue
método que pode ser chamado para forçar uma reavaliação do valor de seu BindableProperty
argumento, invocando seu retorno de chamada de valor de coerção.
Os retornos de chamada de valor de coerção são usados para forçar uma reavaliação de uma propriedade associável quando o valor da propriedade é alterado. Por exemplo, um retorno de chamada de valor de coerção pode ser usado para garantir que o valor de uma propriedade associável não seja maior que o valor de outra propriedade associável.
O exemplo de código a seguir mostra como a Angle
propriedade associável registra o CoerceAngle
método como um método de retorno de chamada de valor de coerção:
public static readonly BindableProperty AngleProperty = BindableProperty.Create (
"Angle", typeof(double), typeof(HomePage), 0.0, coerceValue: CoerceAngle);
public static readonly BindableProperty MaximumAngleProperty = BindableProperty.Create (
"MaximumAngle", typeof(double), typeof(HomePage), 360.0, propertyChanged: ForceCoerceValue);
...
static object CoerceAngle (BindableObject bindable, object value)
{
var homePage = bindable as HomePage;
double input = (double)value;
if (input > homePage.MaximumAngle)
{
input = homePage.MaximumAngle;
}
return input;
}
static void ForceCoerceValue(BindableObject bindable, object oldValue, object newValue)
{
bindable.CoerceValue(AngleProperty);
}
O CoerceAngle
método verifica o valor da MaximumAngle
propriedade e, se o valor da Angle
propriedade for maior que ele, ele coagi o valor ao valor da MaximumAngle
propriedade. Além disso, quando a MaximumAngle
propriedade altera o retorno de chamada do valor coercitório é invocado na Angle
propriedade chamando o CoerceValue
método .
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 exemplo de código a seguir:
public static readonly BindableProperty SizeProperty =
BindableProperty.Create ("Size", typeof(double), typeof(HomePage), 0.0,
defaultValueCreator: bindable => Device.GetNamedSize (NamedSize.Large, (Label)bindable));
O defaultValueCreator
parâmetro é definido como um Func
que invoca o Device.GetNamedSize
método para retornar um double
que representa o tamanho nomeado para a fonte usada em um Label
na plataforma nativa.