Extensões BindableObject

As extensões BindableObject fornecem uma série de métodos de extensão que dão suporte à configuração de Bindings em um BindableObject.

As extensões oferecem os seguintes métodos:

Associar

O método de Bind oferece uma série de sobrecargas que fornecem uma conveniência diferente em torno da configuração de uma Binding. Para obter mais informações sobre as possibilidades de dados Binding em um aplicativo do .NET MAUI, consulte a documentação da Microsoft.

Exemplo

Existem diversas sobrecargas para o método de Bind.

Vinculação unidirecional

Uma vinculação unidirecional de uma propriedade de modelo de exibição (RegistrationViewModel) chamada RegistrationCode à Text propriedade de um Label pode ser criada como se segue:

new Entry()
    .Bind(Label.TextProperty, 
            getter: static (RegistrationViewModel vm) => vm.RegistrationCode)

Vinculação bidirecional

Uma vinculação bidirecional de uma propriedade de modelo de exibição (RegistrationViewModel) chamada RegistrationCode à Text propriedade de um Entry pode ser criada da seguinte maneira:

new Entry()
    .Bind(Entry.TextProperty,
            getter: static (RegistrationViewModel vm) => vm.RegistrationCode,
            setter: static (RegistrationViewModel vm, string code) => vm.RegistrationCode = code)

Vinculações Complexas (Aninhadas)

Ao vincular a uma propriedade dentro de uma propriedade (processo também conhecido como "Vinculações Aninhadas"), o parâmetro handlers é obrigatório. O parâmetro handler requer uma referência a cada Propriedade na cadeia de vinculação complexa.

Junto com o exemplo abaixo, você pode encontrar exemplos adicionais de vinculações complexas nos Testes de Unidade para o CommunityToolkit.Maui.Markup.

Exemplo de Vinculações Complexas (Aninhadas)

Usando a classe ViewModel abaixo, podemos criar uma vinculação bidirecional aninhada diretamente para o ViewModel.NestedObject.Text usando o parâmetro handlers:

new Entry().Bind(
    Entry.TextProperty,
    getter: static (ViewModel vm) => vm.NestedObject.Text,
    handlers: new (Func<ViewModel, object?>, string)[]
             {
                (vm => vm, nameof(ViewModel.NestedObject)),
                (vm => vm.NestedObject, nameof(ViewModel.NestedObject.Text)),
             },
    setter: static (ViewModel vm, string text) => vm.NestedObject.Text = text);
class ViewModel
{
    public NestedObject NestedObject { get; set; } = new();

    public required string Text { get; set; }
}

class NestedObject
{
    public required string Text { get; set; }
}

Propriedade padrão

O método Bind pode ser chamado sem especificar a propriedade para a qual configurar a vinculação, o que irá utilizar os padrões fornecidos pela biblioteca com a lista completa no repositório do GitHub.

A propriedade padrão a ser vinculada para uma Entry é a propriedade de texto. Portanto, o exemplo acima poderia ser escrito como:

new Entry().Bind(nameof(ViewModel.RegistrationCode))

Aviso

Essa abordagem resultará em algum nível de Reflexão sendo usado e não terá um desempenho tão bom quanto a abordagem Propriedade explícita.

Conversão de valor

O método Bind permite que um desenvolvedor forneça o Converter que quiser usar na vinculação ou, simplesmente, forneça um mecanismo a ser usado em uma conversão embutida.

Conversor
new Entry()
    .Bind(Entry.TextProperty,
            getter: static (RegistrationViewModel vm) => vm.RegistrationCode,
            converter: new TextCaseConverter { Type = TextCaseType.Upper });

Confira TextCaseConverter para obter a documentação sobre seu uso completo.

Conversão embutida
new Entry()
    .Bind(Entry.TextProperty,
            getter: static (RegistrationViewModel vm) => vm.RegistrationCode,
            convert: (string? text) => text?.ToUpperInvariant());

Vinculações múltiplas

Vinculações múltiplas podem ser agregadas todas juntas com o uso do IMultiValueConverter.

O parâmetro convert é uma Func que é necessária para converter as vinculações múltiplas no resultado necessário.

new Label()
    .Bind(Label.TextProperty,
            binding1: new Binding(nameof(ViewModel.IsBusy)),
            binding2: new Binding(nameof(ViewModel.LabelText)),
            convert: ((bool IsBusy, string LabelText) values) => values.IsBusy ? string.Empty : values.LabelText)

BindCommand

O método BindCommand fornece uma maneira útil de configurar uma vinculação a um padrão fornecido pela biblioteca com a lista completa no repositório do GitHub.

O comando padrão a ser vinculado a um Button é a propriedade de Command. Portanto, o exemplo a seguir configura uma vinculação a essa propriedade.

new Button().BindCommand(static (ViewModel vm) => vm.SubmitCommand);

O mencionado acima também pode ser escrito como:

Observação

Se o comando padrão não resultar em uma vinculação ao comando desejado, você poderá usar o método Bind.

new Button()
    .Bind(Entry.CommandProperty,
            getter: static (RegistrationViewModel vm) => vm.SubmitCommand,
            mode: BindingMode.OneTime);

Vinculação de Gestos

As vinculações de gestos nos permitem criar um ClickGestureRecognizer, SwipeGestureRecognizer, TapGestureRecognizer, anexá-lo a qualquer elemento que implemente um IGestureRecognizer e associá-lo a um ICommand no nosso ViewModel.

BindClickGesture

O exemplo a seguir demonstra como criar um ClickGestureRecognizer que requer 2 cliques para ser ativado, anexá-lo a um Label e vinculá-lo a uma propriedade de ICommand chamada ClickCommand no nosso ViewModel:

new Label()
    .BindClickGesture(
        static (ViewModel vm) => vm.ClickCommand,
        commandBindingMode: BindingMode.OneTime,
        numberOfClicksRequired: 2));

BindSwipeGesture

O exemplo a seguir demonstra como criar um SwipeGestureRecognizer que requer SwipeDirection.Up para sua SwipeDirection e uma distância mínima de 200 pontos para seu Threshold; a seguir, anexe-o a um Label e o vincule a uma propriedade de ICommand chamada SwipeCommand no nosso ViewModel:

new Label()
    .BindSwipeGesture(
        static (ViewModel vm) => vm.SwipeCommand,
        commandBindingMode: BindingMode.OneTime,
        direction: SwipeDirection.Up,
        threshold: 200);

BindTapGesture

O exemplo a seguir demonstra como criar um ClickGestureRecognizer que requer 2 toques para ser ativado, anexá-lo a um Label e associá-lo a uma propriedade de ICommand chamada TapCommand no nosso ViewModel:

new Label()
    .BindTapGesture(
        static (ViewModel vm) => vm.TapCommand,
        commandBindingMode: BindingMode.OneTime,
        numberOfTapsRequired: 2));

AppThemeBinding

O método AppThemeBinding permite que um valor claro e escuro seja atribuído a uma BindableProperty para que, quando os aplicativos AppTheme forem modificados, o valor apropriado seja usado para o respectivo tema.

O exemplo a seguir atribuirá a cor preta à propriedade Text do controle Label se o aplicativo estiver em execução em um tema claro e a cor branca se estiver em um tema escuro.

new Label().AppThemeBinding(Label.TextColorProperty, Colors.Black, Colors.White);

Observação

Existe um método mais específico ao lidar com propriedades de Color. AppThemeColorBinding executará o mesmo comportamento subjacente que AppThemeBinding, mas requer um conjunto de parâmetros de Color.

Para saber mais, confira a documentação do Uso de Temas.

Exemplos

Você pode encontrar um exemplo desses métodos de extensão em ação em todo a Amostra de aplicativo do Kit de Ferramentas da Comunidade do .NET MAUI.

API

Você pode encontrar o código-fonte para os métodos de extensão de BindableObject no repositório do GitHub do Kit de Ferramentas da Comunidade do .NET MAUI.