Extensão de marcação {x:Bind}

Nota Para obter informações gerais sobre como usar a associação de dados em seu aplicativo com {x:Bind} (e para obter uma comparação completa entre {x:Bind} e {Binding}), consulte Associação de dados detalhadamente.

A extensão de marcação {x: Bind} — nova no Windows 10 — é uma alternativa ao {Binding}. {x:Bind} é executado em menos tempo e menos memória do que {Binding} e dá suporte à melhor depuração.

Em tempo de compilação XAML, {x: Bind} é convertido em código que irá obter um valor de uma propriedade em uma fonte de dados e defini-lo na propriedade especificada na marcação. O objeto de associação, opcionalmente, pode ser configurado para observar mudanças no valor da propriedade de origem de dados e atualizar-se com base nessas alterações (Mode="OneWay"). Ele também pode ser configurado opcionalmente para enviar as alterações em seu próprio valor de volta para a propriedade de origem (Mode="TwoWay").

Os objetos de associação criados por {x:Bind} e {Binding} são em grande parte funcionalmente equivalentes. Mas o {x:Bind} executa o código de finalidade especial, que ele gera no tempo de compilação, e o {Binding} usa inspeção de objeto de tempo de execução de finalidade geral. Consequentemente, as associações {x:Bind} (normalmente chamadas de associações compiladas) têm excelente desempenho, fornecem validação de tempo de compilação de suas expressões de associação e dão suporte à depuração permitindo que você defina pontos de interrupção nos arquivos de código que são gerados como a classe parcial para sua página. Esses arquivos podem ser encontrados em sua pasta obj, com nomes como (para C#) <view name>.g.cs.

Dica

{x:Bind} possui um modo padrão de OneTime, ao contrário de {Binding}, que possui um modo padrão de OneWay. Este foi escolhido por razões de desempenho, já que o uso de OneWay faz com que mais código seja gerado para conectar e manipular a detecção de alteração. Você pode especificar explicitamente um modo para usar a associação OneWay ou TwoWay. É possível usar, também, o x:DefaultBindMode para alterar o modo padrão para {x:Bind} de um segmento específico da árvore de marcação. O modo especificado aplica-se a qualquer expressão {x:Bind} nesse elemento e seus filhos, que não especificam explicitamente um modo como parte da vinculação.

Aplicativos de amostra que demonstram {x:Bind}

Uso do atributo XAML

<object property="{x:Bind}" .../>
-or-
<object property="{x:Bind propertyPath}" .../>
-or-
<object property="{x:Bind bindingProperties}" .../>
-or-
<object property="{x:Bind propertyPath, bindingProperties}" .../>
-or-
<object property="{x:Bind pathToFunction.functionName(functionParameter1, functionParameter2, ...), bindingProperties}" .../>
Termo Descrição
Propertypath Uma cadeia de caracteres que especifica o caminho de propriedade para a associação. Mais informações estão na seção caminho de propriedade abaixo.
bindingProperties
Propname=value[, propName=value]* Uma ou mais propriedades de associação que são especificadas usando uma sintaxe de par nome/valor.
propName O nome da cadeia de caracteres da propriedade a ser definida no objeto Binding. Por exemplo, "Converter".
value O valor para o qual definir a propriedade. A sintaxe do argumento depende da propriedade que está sendo definida. Aqui está um exemplo de umuso de valorpropName= em que o valor é uma extensão de marcação: Converter={StaticResource myConverterClass}. Para obter mais informações, consulte a seção Propriedades que você pode definir com {x: Bind} a seguir.

Exemplos

<Page x:Class="QuizGame.View.HostView" ... >
    <Button Content="{x:Bind Path=ViewModel.NextButtonText, Mode=OneWay}" ... />
</Page>

Este exemplo usa XAML {x: Bind} com uma propriedade ListView.ItemTemplate. Observe a declaração de um valor x: DataType.

  <DataTemplate x:Key="SimpleItemTemplate" x:DataType="data:SampleDataGroup">
    <StackPanel Orientation="Vertical" Height="50">
      <TextBlock Text="{x:Bind Title}"/>
      <TextBlock Text="{x:Bind Description}"/>
    </StackPanel>
  </DataTemplate>

Caminho da propriedade

PropertyPath define a propriedade Path de uma expressão {x:Bind}. Path é um caminho de propriedade que especifica o valor da propriedade, da subpropriedade, do campo ou do método ao qual você está se associando (à origem). Você pode mencionar o nome da propriedade Path explicitamente: {x:Bind Path=...}. Ou você pode omiti-lo: {x:Bind ...}.

Resolução de caminho da propriedade

{x:Bind} não usa o DataContext como uma fonte padrão; em vez disso, usa o controle de página ou do usuário propriamente dito. Portanto, ele aparecerá no code-behind de sua página ou controle de usuário para métodos, propriedades e campos. Para expor seu modelo de exibição {x:Bind}, você geralmente deseja adicionar novos campos ou propriedades para o code-behind para sua página ou controle de usuário. Etapas de um caminho de propriedade são delimitadas por pontos (.), e você pode incluir vários delimitadores para percorrer subpropriedades sucessivas. Use o ponto delimitador independentemente da linguagem de programação usada para implementar o objeto sendo associado.

Por exemplo: em uma página, Text="{x:Bind Employee.FirstName}" procurará por um membro Funcionário na página e, em seguida, um membro FirstName no objeto retornado por Funcionário. Se você estiver associando o controle de um item a uma propriedade que contém dependentes de um funcionário, o seu caminho de propriedade pode ser "Employee.Dependents", o modelo de item do controle do item exibiria os itens em "Dependents".

Para C++/CX, {x:Bind} não é possível associar campos particulares e propriedades no modelo de página ou dados – você precisará ter uma propriedade pública para que seja associável. A área de superfície para associação precisa ser exposta como classes/interfaces CX para que possamos obter os metadados relevantes. O atributo [Associável] não deve ser necessário.

Com x:Bind, você não precisa usar ElementName=xxx como parte da expressão de associação. Em vez disso, você pode usar o nome do elemento como a primeira parte do caminho para a associação porque os elementos nomeados se tornam campos dentro da página ou controle do usuário que representa a origem da associação raiz.

Coleções

Se a fonte de dados for uma colação, um caminho de propriedade pode especificar itens na coleção pela posição ou índice. Por exemplo, "Teams[0]. Players", em que o literal "[]" inclui o "0" que solicita o primeiro item em uma coleção indexada a zero.

Para usar um indexador, o modelo precisa implementar IList<T> ou IVector<T> no tipo de propriedade que vai ser indexada. (Observe que IReadOnlyList<T> e IVectorView<T> não dão suporte à sintaxe do indexador.) Se o tipo da propriedade indexada der suporte a INotifyCollectionChanged ou IObservableVector e a associação for OneWay ou TwoWay, ele registrará e escutará as notificações de alteração nessas interfaces. A lógica de detecção de alteração irá atualizar com base em todas as alterações de coleção, mesmo que não afete o valor indexado específico. Isso ocorre porque a lógica de escuta é comum em todas as instâncias da coleção.

Se a fonte de dados for um dicionário ou um mapa, um caminho de propriedade poderá especificar itens na coleção pelo nome da cadeia de caracteres. Por exemplo <, TextBlock Text="{x:Bind Players['John Smith']}" /> procurará um item no dicionário chamado "John Smith". O nome precisa estar entre aspas, e aspas simples ou duplas podem ser usadas. O acento circunflexo (^) pode ser usado no escape de citações em cadeias de caracteres. Geralmente, é mais fácil usar aspas alternativas daquelas usadas para o atributo XAML. (Observe que IReadOnlyDictionary<T> e IMapView<T> não dão suporte à sintaxe do indexador.)

Para usar um indexador da cadeia de caracteres, o modelo precisa implementar IDictionary<string, T> ou IMap<string, T> no tipo da propriedade que será indexada. Se o tipo da propriedade indexada suportar IObservableMap e a associação for OneWay ou TwoWay, então registrará e escutará notificações de alteração nessas interfaces. A lógica de detecção de alteração irá atualizar com base em todas as alterações de coleção, mesmo que não afete o valor indexado específico. Isso ocorre porque a lógica de escuta é comum em todas as instâncias da coleção.

Propriedades Anexadas

Para associar às propriedades anexadas, você precisa colocar a classe e o nome da propriedade entre parênteses após o ponto. Por exemplo Text="{x:Bind Button22.(Grid.Row)}". Se a propriedade não é declarada em um namespace Xaml, você precisará prefixá-la com um namespace xml, que você deve mapear para um namespace de código no head do documento.

Transmissão

Associações compiladas são fortemente tipadas e resolverão o tipo de cada etapa em um caminho. Se o tipo retornado não tiver o membro, falhará no momento da compilação. Você pode especificar uma conversão para informar o tipo real do objeto de associação.

No caso a seguir, obj é uma propriedade do objeto de tipo, mas que contém uma caixa de texto, para que possamos usar Text="{x:Bind ((TextBox)obj).Text}" ou Text="{x:Bind obj.(TextBox.Text)}".

O campo groups3 em Text="{x:Bind ((data:SampleDataGroup)groups3[0]). Title}" é um dicionário de objetos, portanto, você deve convertê-lo em data:SampleDataGroup. Observe o uso do prefixo de namespace xml data: para mapear o tipo de objeto para um namespace de código que não seja parte do namespace XAML padrão.

Observação: A sintaxe de conversão em estilo C# é mais flexível do que a sintaxe de propriedade anexada, e será a sintaxe recomendada futuramente.

Conversão sem caminho

O analisador de associação nativa não fornece uma palavra-chave para representar this como um parâmetro de função, mas dá suporte à conversão sem caminho (por exemplo, {x:Bind (x:String)}), que pode ser usada como um parâmetro de função. Portanto, {x:Bind MethodName((namespace:TypeOfThis))} é uma maneira válida de executar o que é conceitualmente equivalente a {x:Bind MethodName(this)}.

Exemplo:

Text="{x:Bind local:MainPage.GenerateSongTitle((local:SongItem))}"

<Page
    x:Class="AppSample.MainPage"
    ...
    xmlns:local="using:AppSample">

    <Grid>
        <ListView ItemsSource="{x:Bind Songs}">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="local:SongItem">
                    <TextBlock
                        Margin="12"
                        FontSize="40"
                        Text="{x:Bind local:MainPage.GenerateSongTitle((local:SongItem))}" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Page>
namespace AppSample
{
    public class SongItem
    {
        public string TrackName { get; private set; }
        public string ArtistName { get; private set; }

        public SongItem(string trackName, string artistName)
        {
            ArtistName = artistName;
            TrackName = trackName;
        }
    }

    public sealed partial class MainPage : Page
    {
        public List<SongItem> Songs { get; }
        public MainPage()
        {
            Songs = new List<SongItem>()
            {
                new SongItem("Track 1", "Artist 1"),
                new SongItem("Track 2", "Artist 2"),
                new SongItem("Track 3", "Artist 3")
            };

            this.InitializeComponent();
        }

        public static string GenerateSongTitle(SongItem song)
        {
            return $"{song.TrackName} - {song.ArtistName}";
        }
    }
}

Funções em caminhos de associação

Desde o Windows 10, versão 1607, {x: Bind} dá suporte ao uso de uma função como a etapa de folha do caminho de associação. Esse é um recurso avançado para vinculação de dados que permite vários cenários na marcação. Confira associações de função para obter detalhes.

Associação de evento

Associação de evento é um recurso exclusivo para associação compilada. Permite que você especifique o manipulador para um evento usando uma associação, em vez de ele ter de ser um método no code-behind. Por exemplo: Click="{x:Bind rootFrame.GoForward}".

Para eventos, o método de destino não deve ser sobrecarregado e também deve:

  • Corresponder à assinatura do evento.
  • OU não ter parâmetros.
  • OU ter o mesmo número de parâmetros de tipos que podem ser atribuídos com base nos tipos dos parâmetros de evento.

No code-behind gerado, associação compilada manipula o evento e o encaminha para o método no modelo, avaliando o caminho da expressão de associação quando o evento ocorre. Isso significa que, diferentemente das associações de propriedade, não controla as alterações no modelo.

Para saber mais sobre a sintaxe de cadeia de caracteres de um caminho de propriedade, veja Sintaxe de caminho de propriedade, tendo em mente as diferenças descritas aqui para {x:Bind}.

Propriedades que você pode definir com {x: Bind}

{x:Bind} é ilustrado com a sintaxe de espaço reservado bindingProperties porque há várias propriedades de leitura/gravação que podem ser definidas na extensão de marcação. As propriedades podem ser definidas em qualquer ordem com pares devalorpropName= separados por vírgulas. Observe que você não pode incluir quebras de linha na expressão de associação. Algumas das propriedades exigem tipos que não têm uma conversão de tipo específica, então são necessárias extensões de marcação próprias aninhadas no {x:Bind}.

Essas propriedades funcionam da mesma forma que as propriedades da classe Binding.

Propriedade Descrição
Caminho Consulte a seção Caminho de propriedade acima.
Conversor Especifica o objeto de conversor que é chamado pelo mecanismo de associação. O conversor pode ser definido em XAML, mas somente se você se referir a uma instância de objeto atribuída em uma referência {StaticResource} markup extension ao objeto no dicionário de recursos.
ConverterLanguage Especifica a cultura a ser usada pelo conversor. (Se você estiver configurando ConverterLanguage também deverá configurar Converter.) A cultura é definida como um identificador baseado em padrões. Para obter mais informações, consulte ConverterLanguage.
ConverterParameter Especifica o parâmetro do conversor que pode ser usado na lógica de conversão. (Se estiver definindo ConverterParameter, você também deve definir Converter). A maioria dos conversores usam lógica simples que obtém todas as informações que precisam do valor calculado para converter, e não precisam de um valor ConverterParameter. O parâmetro ConverterParameter é para implementações moderadamente avançadas que têm mais de uma lógica que controla o que for passado em ConverterParameter. Você também pode escrever um conversor que usa valores diferentes de cadeias de caracteres, mas isso é incomum; veja Comentários em ConverterParameter para saber mais.
FallbackValue Especifica um valor a ser exibido quando a fonte ou caminho não podem ser resolvidos.
Modo Especifica o mode de associação como uma dessas cadeias de caracteres: "OneTime", "OneWay" ou "TwoWay". O padrão é "OneTime". Observe que isso é diferente do padrão para {Binding}, que é "OneWay" na maioria dos casos.
TargetNullValue Especifica um valor a ser exibido quando o valor de origem é solucionado, mas é explicitamente null.
BindBack Especifica uma função a ser usada na direção inversa de uma associação bidirecional.
UpdateFonteTrigger Especifica quando enviar as alterações de volta a partir do controle para o modelo na associações de TwoWay. O padrão para todas as propriedades, exceto TextBox.Text, é PropertyChanged; TextBox.Text é LostFocus.

Observação

Se você estiver convertendo a marcação de {Binding} em {x:Bind}, examine as diferenças nos valores padrão da propriedade Mode. x:DefaultBindMode pode ser usado para alterar o modo padrão para x:Bind de um segmento específico da árvore de marcação. O modo selecionado aplicará qualquer expressão x:Bind nesse elemento e seus filhos, que não especificam explicitamente um modo como parte da vinculação. OneTime é mais eficiente do que OneWay, uma vez que usar OneWay fará com que mais código seja gerado para conectar e manipular a detecção de alteração.

Comentários

Como {x:Bind} usa código gerado para atingir seus benefícios, requer informações de tipo em tempo de compilação. Isso significa que você não pode associar a propriedades onde você não souber o tipo antes do tempo. Por isso, você não pode usar {x:Bind} com a propriedade DataContext, que é do tipo Object e também está sujeita a alterações no tempo de execução.

Ao usar {x:Bind} com modelos de dados, você deve indicar o tipo que está sendo associado definindo um valor x:DataType , conforme mostrado na seção Exemplos . Você pode também definir o tipo para um tipo de classe de interface ou base, e então use projeções, se necessário, para formular uma expressão completa.

As associações compiladas dependem da geração de código. Portanto, se você usar {x:Bind} em um dicionário de recursos, o dicionário de recursos precisará ter uma classe code-behind. Veja Dicionários de recursos com {x:Bind} para obter um exemplo de código.

Páginas e controles de usuário que incluem associações compiladas terão uma propriedade "Bindings" no código gerado. Entre elas estão os seguintes métodos:

  • Update() - Isso atualizará os valores de todas as associações compiladas. Uma associação unidirecional/bidirecional terá os ouvintes conectados para detectar alterações.
  • Initialize() - Se as associações ainda não tiverem sido inicializadas, ela chamará Update() para inicializá-las
  • StopTracking() - Ela desconectará todos os ouvintes criados para associações uni e bidirecionais. Elas podem ser reinicializadas usando-se o método Update().

Observação

A partir do Windows 10, versão 1607, a estrutura XAML fornece um Booleano integrado para conversor de Visibilidade. O conversor mapeia true para o valor de enumeração Visible e false para Collapsed para que você possa associar uma propriedade Visibility a um booliano sem criar um conversor. Observe que isso não é um recurso de associação de função e sim de associação de propriedade. Para usar o conversor integrado, a versão do SDK de alvo mínimo do seu aplicativo deve ser 14393 ou posterior. Você não poderá usá-lo se seu aplicativo for voltado para versões anteriores do Windows 10. Para saber mais sobre as versões de destino, consulte Código adaptável de versão.

Ponta Se você precisar especificar uma única chave para um valor, como em Path ou ConverterParameter, preceda-a com uma barra invertida: \{. De forma alternativa, colo a cadeia de caracteres inteira que contém a chave que precisa de escape entre apóstrofos; por exemplo, ConverterParameter='{Mix}'.

Converter, ConverterLanguage e ConverterLanguage estão todos relacionados à situação de conversão de um valor ou tipo de uma fonte de associação a um tipo ou valor que é compatível com a propriedade do destino da associação. Para saber mais, veja a seção "Conversões de dados" em Vinculação de dados em detalhes.

{x:Bind} é apenas uma extensão de marcação, sem nenhuma maneira de criar ou manipular essas associações de forma programática. Para saber mais sobre extensões de marcação, veja Visão geral do XAML.