Comportamentos
Os comportamentos da IU do aplicativo multiplataforma do .NET (.NET MAUI) permitem adicionar funcionalidade aos controles da interface do usuário sem precisar subclassificá-los. Em vez disso, a funcionalidade é implementada em uma classe de comportamento e anexada ao controle como se fizesse parte do próprio controle.
Os comportamentos permitem que você implemente código que normalmente precisaria escrever como code-behind, porque interagem diretamente com a API do controle, de forma que podem ser anexados de forma concisa ao controle e empacotados para reutilização em mais de um aplicativo. Eles podem ser usados para fornecer uma ampla gama de funcionalidade para controles, como:
- Adicionar um validador de email a um Entry.
- Criar um controle de classificação usando um reconhecedor de gesto de toque.
- Controlar uma animação.
O .NET MAUI oferece suporte a três tipos diferentes de comportamentos:
- Comportamentos anexados são classes
static
com uma ou mais propriedades anexadas. Para obter mais informações sobre comportamentos anexados, consulte Comportamentos anexados. - Comportamentos MAUI do .NET são classes que derivam da Behavior classe ou Behavior<T> , onde
T
é o tipo do controle ao qual o comportamento deve se aplicar. Para obter mais informações, consulte Comportamentos do .NET MAUI. - Os comportamentos de plataforma são classes derivadas da PlatformBehavior<TView> classe ou PlatformBehavior<TView,TPlatformView> . Esses comportamentos podem responder a condições e eventos arbitrários em um controle nativo. Para obter mais informações, consulte Comportamentos de plataforma.
Comportamentos anexados
Comportamentos anexados são classes estáticas com uma ou mais propriedades anexadas. Uma propriedade anexada é um tipo especial de propriedade associável. Elas são definidas em uma classe, mas são anexadas a outros objetos e reconhecíveis no XAML como atributos que contêm uma classe e um nome de propriedade separados por um ponto. Para obter mais informações sobre propriedades anexadas, consulte Propriedades anexadas.
Uma propriedade anexada pode definir um delegado propertyChanged
que será executado quando o valor da propriedade for alterado, por exemplo, quando a propriedade for definida em um controle. Quando o delegado propertyChanged
é executado, é passada a ele uma referência ao controle a que ele está sendo anexado, bem como parâmetros que contêm os valores antigo e novo da propriedade. Esse delegado pode ser usado para adicionar uma nova funcionalidade ao controle a que a propriedade está anexada manipulando a referência que é passada, da seguinte maneira:
- O delegado
propertyChanged
converte a referência do controle, que é recebida como um BindableObject, para o tipo de comportamento que o controle deve melhorar. - O delegado
propertyChanged
modifica as propriedades do controle, chama os métodos do controle ou registra manipuladores de eventos para eventos expostos pelo controle, a fim de implementar a funcionalidade do comportamento de núcleo.
Aviso
Os comportamentos anexados são definidos em uma static
classe, com static
propriedades e métodos. Isso dificulta a criação de comportamentos anexados com estado.
Criar um comportamento anexado
Um comportamento anexado pode ser implementado criando uma classe estática que contém uma propriedade anexada que especifica um propertyChanged
delegado.
O exemplo a seguir mostra a AttachedNumericValidationBehavior
classe, que destaca o valor inserido pelo usuário em um controle em vermelho se não for um Entrydouble
:
public static class AttachedNumericValidationBehavior
{
public static readonly BindableProperty AttachBehaviorProperty =
BindableProperty.CreateAttached("AttachBehavior", typeof(bool), typeof(AttachedNumericValidationBehavior), false, propertyChanged: OnAttachBehaviorChanged);
public static bool GetAttachBehavior(BindableObject view)
{
return (bool)view.GetValue(AttachBehaviorProperty);
}
public static void SetAttachBehavior(BindableObject view, bool value)
{
view.SetValue(AttachBehaviorProperty, value);
}
static void OnAttachBehaviorChanged(BindableObject view, object oldValue, object newValue)
{
Entry entry = view as Entry;
if (entry == null)
{
return;
}
bool attachBehavior = (bool)newValue;
if (attachBehavior)
{
entry.TextChanged += OnEntryTextChanged;
}
else
{
entry.TextChanged -= OnEntryTextChanged;
}
}
static void OnEntryTextChanged(object sender, TextChangedEventArgs args)
{
double result;
bool isValid = double.TryParse(args.NewTextValue, out result);
((Entry)sender).TextColor = isValid ? Colors.Black : Colors.Red;
}
}
Neste exemplo, a classe contém uma propriedade anexada nomeada AttachBehavior
com um static
getter e setter, que controla a AttachedNumericValidationBehavior
adição ou remoção do comportamento ao controle ao qual ele será anexado. Essa propriedade anexada registra o método OnAttachBehaviorChanged
que será executado quando o valor da propriedade for alterado. Esse método registra ou cancela o registra de um manipulador de eventos para o evento TextChanged
, com base no valor da propriedade anexada AttachBehavior
. A funcionalidade principal do comportamento é fornecida pelo OnEntryTextChanged
método, que analisa o valor inserido no Entry e define a TextColor
propriedade como vermelho se o valor não for um double
.
Consumir um comportamento anexado
Um comportamento anexado pode ser consumido definindo sua propriedade anexada no controle de destino.
O exemplo a seguir mostra o consumo da AttachedNumericValidationBehavior
classe em um Entry adicionando a propriedade anexada AttachBehavior
Entryao :
<ContentPage ...
xmlns:local="clr-namespace:BehaviorsDemos">
<Entry Placeholder="Enter a System.Double" local:AttachedNumericValidationBehavior.AttachBehavior="true" />
</ContentPage>
O Entry equivalente em C# é mostrado no exemplo de código a seguir:
Entry entry = new Entry { Placeholder = "Enter a System.Double" };
AttachedNumericValidationBehavior.SetAttachBehavior(entry, true);
A captura de tela a seguir mostra o comportamento anexado respondendo a entrada inválida:
Observação
Comportamentos anexados são escritos para um tipo de controle específico (ou uma superclasse que pode ser aplicada a muitos controles) e só devem ser adicionados a um controle compatível.
Remover um comportamento anexado
A AttachedNumericValidationBehavior
classe pode ser removida de um controle definindo a propriedade anexada AttachBehavior
como false
:
<Entry Placeholder="Enter a System.Double" local:AttachedNumericValidationBehavior.AttachBehavior="false" />
No runtime, o método OnAttachBehaviorChanged
será executado quando o valor da propriedade anexada AttachBehavior
for definida como false
. O OnAttachBehaviorChanged
método cancelará o registro do manipulador de eventos para o evento, garantindo que o comportamento não seja executado à medida que você interage com o TextChanged
controle.
Comportamentos do .NET MAUI
Os comportamentos do .NET MAUI são criados derivando da Behavior classe ou Behavior<T> .
O processo para criar um comportamento MAUI do .NET é o seguinte:
- Criar uma classe que herda da classe Behavior ou Behavior<T>, em que
T
é o tipo do controle ao qual o comportamento deve ser aplicado. - Substituir o método OnAttachedTo para executar qualquer configuração necessária.
- Substituir o método OnDetachingFrom para executar qualquer limpeza necessária.
- Implementar a funcionalidade principal do comportamento.
Isso resulta na estrutura mostrada no exemplo a seguir:
public class MyBehavior : Behavior<View>
{
protected override void OnAttachedTo(View bindable)
{
base.OnAttachedTo(bindable);
// Perform setup
}
protected override void OnDetachingFrom(View bindable)
{
base.OnDetachingFrom(bindable);
// Perform clean up
}
// Behavior implementation
}
O OnAttachedTo método é chamado imediatamente após o comportamento é anexado a um controle. Esse método recebe uma referência ao controle ao qual ele está anexado e pode ser usado para registrar manipuladores de eventos ou para realizar outra configuração necessária para dar suporte à funcionalidade do comportamento. Por exemplo, você pode assinar um evento em um controle. A funcionalidade do comportamento, então, seria implementada no manipulador do evento.
O OnDetachingFrom método é chamado quando o comportamento é removido do controle. Esse método recebe uma referência ao controle ao qual ele está anexado e é usado para executar qualquer limpeza necessária. Por exemplo, você poderia cancelar a assinatura de um evento em um controle para evitar perdas de memória.
O comportamento pode então ser consumido anexando-o Behaviors à coleção do controle.
Criar um comportamento MAUI do .NET
Um comportamento .NET Maui pode ser implementado criando uma classe que deriva da classe or e substituindo os BehaviorOnAttachedTo métodos eOnDetachingFrom.Behavior<T>
O exemplo a seguir mostra a NumericValidationBehavior
classe, que destaca o valor inserido pelo usuário em um controle em vermelho se não for um Entrydouble
:
public class NumericValidationBehavior : Behavior<Entry>
{
protected override void OnAttachedTo(Entry entry)
{
entry.TextChanged += OnEntryTextChanged;
base.OnAttachedTo(entry);
}
protected override void OnDetachingFrom(Entry entry)
{
entry.TextChanged -= OnEntryTextChanged;
base.OnDetachingFrom(entry);
}
void OnEntryTextChanged(object sender, TextChangedEventArgs args)
{
double result;
bool isValid = double.TryParse(args.NewTextValue, out result);
((Entry)sender).TextColor = isValid ? Colors.Black : Colors.Red;
}
}
Neste exemplo, a NumericValidationBehavior
classe deriva da Behavior<T> classe, onde T
é um Entryarquivo . O método OnAttachedTo registra um manipulador de eventos para o evento TextChanged
, com o método OnDetachingFrom cancelando o registro do evento TextChanged
para evitar perdas de memória. A funcionalidade principal do comportamento é fornecida pelo OnEntryTextChanged
método, que analisa o valor inserido no Entry e define a TextColor
propriedade como vermelho se o valor não for um double
.
Importante
O .NET MAUI não define o de um comportamento, porque os BindingContext
comportamentos podem ser compartilhados e aplicados a vários controles por meio de estilos.
Consumir um comportamento MAUI do .NET
Cada controle MAUI do .NET tem uma Behaviors coleção, à qual um ou mais comportamentos podem ser adicionados:
<Entry Placeholder="Enter a System.Double">
<Entry.Behaviors>
<local:NumericValidationBehavior />
</Entry.Behaviors>
</Entry>
O Entry equivalente em C# é mostrado no exemplo de código a seguir:
Entry entry = new Entry { Placeholder = "Enter a System.Double" };
entry.Behaviors.Add(new NumericValidationBehavior());
A captura de tela a seguir mostra o comportamento do .NET MAUI respondendo a entrada inválida:
Aviso
Os comportamentos MAUI do .NET são escritos para um tipo de controle específico (ou uma superclasse que pode se aplicar a muitos controles) e só devem ser adicionados a um controle compatível. A tentativa de anexar um comportamento MAUI do .NET a um controle incompatível resultará em uma exceção sendo lançada.
Consumir um comportamento MAUI do .NET com um estilo
Os comportamentos do .NET MAUI podem ser consumidos por um estilo explícito ou implícito. No entanto, não é possível criar um estilo que define a propriedade Behaviors de um controle porque a propriedade é somente leitura. A solução é adicionar uma propriedade anexada à classe do comportamento que controla a adição e a remoção do comportamento. O processo é o seguinte:
- Adicione uma propriedade anexada à classe de comportamento que será usada para controlar a adição ou remoção do comportamento ao controle ao qual o comportamento será anexado. Certifique-se de que a propriedade anexada registre um delegado
propertyChanged
que será executado quando o valor da propriedade for alterado. - Crie um getter e setter
static
para a propriedade anexada. - Implemente a lógica no delegado
propertyChanged
para adicionar e remover o comportamento.
O exemplo a seguir mostra a NumericValidationStyleBehavior
classe, que tem uma propriedade anexada que controla a adição e remoção do comportamento:
public class NumericValidationStyleBehavior : Behavior<Entry>
{
public static readonly BindableProperty AttachBehaviorProperty =
BindableProperty.CreateAttached("AttachBehavior", typeof(bool), typeof(NumericValidationStyleBehavior), false, propertyChanged: OnAttachBehaviorChanged);
public static bool GetAttachBehavior(BindableObject view)
{
return (bool)view.GetValue(AttachBehaviorProperty);
}
public static void SetAttachBehavior(BindableObject view, bool value)
{
view.SetValue(AttachBehaviorProperty, value);
}
static void OnAttachBehaviorChanged(BindableObject view, object oldValue, object newValue)
{
Entry entry = view as Entry;
if (entry == null)
{
return;
}
bool attachBehavior = (bool)newValue;
if (attachBehavior)
{
entry.Behaviors.Add(new NumericValidationStyleBehavior());
}
else
{
Behavior toRemove = entry.Behaviors.FirstOrDefault(b => b is NumericValidationStyleBehavior);
if (toRemove != null)
{
entry.Behaviors.Remove(toRemove);
}
}
}
protected override void OnAttachedTo(Entry entry)
{
entry.TextChanged += OnEntryTextChanged;
base.OnAttachedTo(entry);
}
protected override void OnDetachingFrom(Entry entry)
{
entry.TextChanged -= OnEntryTextChanged;
base.OnDetachingFrom(entry);
}
void OnEntryTextChanged(object sender, TextChangedEventArgs args)
{
double result;
bool isValid = double.TryParse(args.NewTextValue, out result);
((Entry)sender).TextColor = isValid ? Colors.Black : Colors.Red;
}
}
Neste exemplo, a classe contém uma propriedade anexada nomeada AttachBehavior
com um static
getter e setter, que controla a NumericValidationStyleBehavior
adição ou remoção do comportamento ao controle ao qual ele será anexado. Essa propriedade anexada registra o método OnAttachBehaviorChanged
que será executado quando o valor da propriedade for alterado. Esse método adiciona ou remove o comportamento do controle com base no valor da propriedade anexada AttachBehavior
.
O seguinte exemplo de código mostra um estilo explícito para o NumericValidationStyleBehavior
que usa a propriedade anexada AttachBehavior
e que pode ser aplicado a controles Entry:
<Style x:Key="NumericValidationStyle" TargetType="Entry">
<Style.Setters>
<Setter Property="local:NumericValidationStyleBehavior.AttachBehavior" Value="true" />
</Style.Setters>
</Style>
O Style pode ser aplicado a um Entry definindo sua Style propriedade para o estilo usando a extensão de StaticResource
marcação:
<Entry Placeholder="Enter a System.Double" Style="{StaticResource NumericValidationStyle}">
Para mais informações sobre estilos, confira Estilos.
Observação
Embora seja possível adicionar propriedades vinculáveis a um comportamento definido ou consultado no XAML, se você criar comportamentos com estado, eles não deverão ser compartilhados entre os controles em um Style em um ResourceDictionary.
Remover um comportamento MAUI do .NET
O OnDetachingFrom método é chamado quando um comportamento é removido de um controle e é usado para executar qualquer limpeza necessária, como cancelar a assinatura de um evento para evitar um vazamento de memória. No entanto, os comportamentos não são removidos implicitamente dos controles, a menos que a coleção do Behaviors controle seja modificada pelo Remove
método ou Clear
:
Behavior toRemove = entry.Behaviors.FirstOrDefault(b => b is NumericValidationStyleBehavior);
if (toRemove != null)
{
entry.Behaviors.Remove(toRemove);
}
Como alternativa, a coleta do Behaviors controle pode ser limpa:
entry.Behaviors.Clear();
Observação
Os comportamentos do .NET MAUI não são removidos implicitamente dos controles quando as páginas são exibidas da pilha de navegação. Em vez disso, eles devem ser removidos explicitamente antes que páginas saiam do escopo.
Comportamentos da plataforma
Os comportamentos da plataforma são criados derivando da PlatformBehavior<TView> classe ou PlatformBehavior<TView,TPlatformView> . Eles respondem a condições e eventos arbitrários em um controle nativo.
Um comportamento de plataforma pode ser implementado por meio de compilação condicional ou classes parciais. A abordagem adotada aqui é usar classes parciais, onde um comportamento de plataforma normalmente consiste em uma classe parcial de plataforma cruzada que define a API de comportamentos e uma classe parcial nativa que implementa o comportamento em cada plataforma. Em tempo de compilação, a multisegmentação combina as classes parciais para criar o comportamento da plataforma em cada plataforma.
O processo para criar um comportamento de plataforma é o seguinte:
Crie uma classe parcial entre plataformas que defina a API para o comportamento da plataforma.
Crie uma classe parcial nativa em cada plataforma para a qual seu aplicativo foi criado, que tenha o mesmo nome da classe parcial entre plataformas. Essa classe parcial nativa deve herdar da PlatformBehavior<TView> classe ou PlatformBehavior<TView,TPlatformView> , onde
TView
é o controle entre plataformas ao qual o comportamento deve se aplicar eTPlatformView
é a exibição nativa que implementa o controle entre plataformas em uma plataforma específica.Observação
Embora seja necessário criar uma classe parcial nativa em cada plataforma para a qual seu aplicativo foi criado, não é necessário implementar a funcionalidade de comportamento da plataforma em todas as plataformas. Por exemplo, você pode criar um comportamento de plataforma que modifique a espessura da borda de um controle nativo em algumas, mas não em todas, plataformas.
Em cada classe parcial nativa necessária para implementar o comportamento da plataforma, você deve:
- Substitua o OnAttachedTo método para executar qualquer configuração.
- Substitua o OnDetachedFrom método para executar qualquer limpeza.
- Implemente a funcionalidade principal do comportamento da plataforma.
O comportamento pode então ser consumido anexando-o Behaviors à coleção do controle.
Criar um comportamento de plataforma
Para criar um comportamento de plataforma, você deve primeiro criar uma classe parcial de plataforma cruzada que defina a API para o comportamento da plataforma:
namespace BehaviorsDemos
{
public partial class TintColorBehavior
{
public static readonly BindableProperty TintColorProperty =
BindableProperty.Create(nameof(TintColor), typeof(Color), typeof(TintColorBehavior));
public Color TintColor
{
get => (Color)GetValue(TintColorProperty);
set => SetValue(TintColorProperty, value);
}
}
}
O comportamento da plataforma é uma classe parcial cuja implementação será concluída em cada plataforma necessária com uma classe parcial adicional que usa o mesmo nome. Neste exemplo, a classe define uma única propriedade vinculável, , TintColor
que matizará uma imagem com a TintColorBehavior
cor especificada.
Depois de criar a classe parcial de plataforma cruzada, você deve criar uma classe parcial nativa em cada plataforma para a qual você cria o aplicativo. Isso pode ser feito adicionando classes parciais às pastas filhas necessárias da pasta Plataformas :
Como alternativa, você pode configurar seu projeto para oferecer suporte a multidirecionamento baseado em nome de arquivo, multidirecionamento baseado em pasta ou ambos. Para obter mais informações sobre multisegmentação, consulte Configurar multisegmentação.
As classes parciais nativas devem herdar da PlatformBehavior<TView> classe ou da PlatformBehavior<TView,TPlatformView> classe, onde TView
é o controle entre plataformas ao qual o comportamento deve se aplicar e TPlatformView
é a exibição nativa que implementa o controle entre plataformas em uma plataforma específica. Em cada classe parcial nativa necessária para implementar o comportamento da plataforma, você deve substituir o método e o OnAttachedToOnDetachedFrom método e implementar a funcionalidade principal do comportamento da plataforma.
O OnAttachedTo método é chamado imediatamente após o comportamento da plataforma ser anexado a um controle de plataforma cruzada. O método recebe uma referência ao controle de plataforma cruzada ao qual ele está anexado e, opcionalmente, uma referência ao controle nativo que implementa o controle de plataforma cruzada. O método pode ser usado para registrar manipuladores de eventos ou executar outra configuração necessária para oferecer suporte à funcionalidade de comportamento da plataforma. Por exemplo, você pode assinar um evento em um controle. A funcionalidade do comportamento, então, seria implementada no manipulador do evento.
O OnDetachedFrom método é chamado quando o comportamento é removido do controle de plataforma cruzada. O método recebe uma referência ao controle ao qual ele está anexado e, opcionalmente, uma referência ao controle nativo que implementa o controle entre plataformas. O método deve ser usado para executar qualquer limpeza necessária. Por exemplo, você poderia cancelar a assinatura de um evento em um controle para evitar perdas de memória.
Importante
As classes parciais devem residir no mesmo namespace e usar nomes idênticos.
O exemplo a seguir mostra a TintColorBehavior
classe parcial para Android, que matiza uma imagem com uma cor especificada:
using Android.Graphics;
using Android.Widget;
using Microsoft.Maui.Platform;
using Color = Microsoft.Maui.Graphics.Color;
namespace BehaviorsDemos
{
public partial class TintColorBehavior : PlatformBehavior<Image, ImageView>
{
protected override void OnAttachedTo(Image bindable, ImageView platformView)
{
base.OnAttachedTo(bindable, platformView);
if (bindable is null)
return;
if (TintColor is null)
ClearColor(platformView);
else
ApplyColor(platformView, TintColor);
}
protected override void OnDetachedFrom(Image bindable, ImageView platformView)
{
base.OnDetachedFrom(bindable, platformView);
if (bindable is null)
return;
ClearColor(platformView);
}
void ApplyColor(ImageView imageView, Color color)
{
imageView.SetColorFilter(new PorterDuffColorFilter(color.ToPlatform(), PorterDuff.Mode.SrcIn ?? throw new NullReferenceException()));
}
void ClearColor(ImageView imageView)
{
imageView.ClearColorFilter();
}
}
}
Neste exemplo, a TintColorBehavior
classe deriva da PlatformBehavior<TView,TPlatformView> classe, onde TView
é um e TPlatformView
é um ImageImageView. O OnAttachedTo aplica a cor de tonalidade à imagem, desde que a TintColor
propriedade tenha um valor. O OnDetachedFrom método remove a cor da tonalidade da imagem.
Uma classe parcial nativa deve ser adicionada em cada plataforma para a qual você cria seu aplicativo. No entanto, você pode fazer a classe parcial nativa NO-OP, se o comportamento da plataforma não for necessário em uma plataforma específica. Isso pode ser alcançado fornecendo uma classe vazia:
using Microsoft.UI.Xaml;
namespace BehaviorsDemos
{
public partial class TintColorBehavior : PlatformBehavior<Image, FrameworkElement>
{
// NO-OP on Windows
}
}
Importante
O .NET MAUI não define o BindingContext
comportamento de uma plataforma.
Consumir um comportamento de plataforma
Cada controle .NET MAUI tem uma Behaviors coleção, à qual um ou mais comportamentos de plataforma podem ser adicionados:
<Image Source="dotnet_bot.png"
HeightRequest="200"
HorizontalOptions="Center">
<Image.Behaviors>
<local:TintColorBehavior TintColor="Red" />
</Image.Behaviors>
</Image>
O equivalente Image em C# é mostrado no exemplo a seguir:
Image image = new Image { Source = "dotnet_bot.png", HeightRequest = 200, HorizontalOptions = LayoutOptions.Center };
image.Behaviors.Add(new TintColorBehavior());
A captura de tela a seguir mostra o comportamento da plataforma matizando uma imagem:
Aviso
Os comportamentos de plataforma são escritos para um tipo de controle específico (ou uma superclasse que pode se aplicar a muitos controles) e só devem ser adicionados a um controle compatível. A tentativa de anexar um comportamento de plataforma a um controle incompatível resultará em uma exceção sendo lançada.
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: Ao longo de 2024, eliminaremos os problemas do GitHub como o mecanismo de comentários para conteúdo e o substituiremos por um novo sistema de comentários. Para obter mais informações, consulteEnviar e exibir comentários de