Xamarin.Forms Associações compiladas

Baixar exemplo Baixar o exemplo

As associações compiladas são resolvidas mais rapidamente do que as associações clássicas, melhorando o desempenho da associação de dados em Xamarin.Forms aplicativos.

Associações de dados têm dois problemas principais:

  1. Não há validação em tempo de compilação para expressões de associação. Em vez disso, as associações são resolvidas em runtime. Sendo assim, associações inválidas não são detectadas até o runtime, quando o aplicativo não se comporta conforme esperado ou mensagens de erro são exibidas.
  2. Elas não são econômicas. Associações são resolvidas em runtime usando a inspeção de objeto para uso geral (reflexão), e a sobrecarga de fazer isso varia de uma plataforma para outra.

As associações compiladas melhoram o desempenho da associação de dados em Xamarin.Forms aplicativos resolvendo expressões de associação em tempo de compilação em vez de runtime. Além disso, essa validação em tempo de compilação das expressões de associação permite uma melhor experiência de solução de problemas para o desenvolvedor porque associações inválidas são relatadas como erros de build.

O processo para usar associações compiladas é:

  1. Habilitar a compilação de XAML. Para obter mais informações sobre a compilação de XAML, confira Compilação de XAML.
  2. Definir um atributo x:DataType em um VisualElement como o tipo do objeto ao qual VisualElement e seus filhos se associarão.

Observação

É recomendável definir o atributo x:DataType no mesmo nível da hierarquia de exibição em que BindingContext está definido. No entanto, esse atributo pode ser redefinido em qualquer local em uma hierarquia de exibição.

Para usar associações compiladas, o x:DataType atributo deve ser definido como um literal de cadeia de caracteres ou um tipo usando a x:Type extensão de marcação. No tempo de compilação de XAML, as expressões de associação inválidas serão relatadas como erros de build. No entanto, o compilador XAML relatará um erro de build somente para a primeira expressão de associação inválida que encontrar. Expressões de associação válidas definidas no VisualElement ou em seus filhos serão compiladas, independentemente de BindingContext estar definido no XAML ou no código. Compilar uma expressão de associação gera o código compilado que obterá um valor de uma propriedade na origem e o definirá na propriedade de destino especificada na marcação. Além disso, dependendo da expressão de associação, o código gerado poderá observar alterações no valor da propriedade de origem e atualizar a propriedade de destino, e pode enviar por push alterações do destino para a origem.

Importante

Atualmente, associações compiladas estão desabilitadas para expressões de associação que definem a propriedade Source. Isso acontece porque a propriedade Source sempre é definida usando a extensão de marcação x:Reference, que não pode ser resolvida em tempo de compilação.

Usar associações compiladas

A página Seletor de Cor Compilada demonstra o uso de associações compiladas entre Xamarin.Forms exibições e propriedades viewmodel:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:DataBindingDemos"
             x:Class="DataBindingDemos.CompiledColorSelectorPage"
             Title="Compiled Color Selector">
    ...
    <StackLayout x:DataType="local:HslColorViewModel">
        <StackLayout.BindingContext>
            <local:HslColorViewModel Color="Sienna" />
        </StackLayout.BindingContext>
        <BoxView Color="{Binding Color}"
                 ... />
        <StackLayout Margin="10, 0">
            <Label Text="{Binding Name}" />
            <Slider Value="{Binding Hue}" />
            <Label Text="{Binding Hue, StringFormat='Hue = {0:F2}'}" />
            <Slider Value="{Binding Saturation}" />
            <Label Text="{Binding Saturation, StringFormat='Saturation = {0:F2}'}" />
            <Slider Value="{Binding Luminosity}" />
            <Label Text="{Binding Luminosity, StringFormat='Luminosity = {0:F2}'}" />
        </StackLayout>
    </StackLayout>    
</ContentPage>

O StackLayout raiz instancia o HslColorViewModel e inicializa a propriedade Color dentro de marcas de elemento de propriedade para a propriedade BindingContext. Essa raiz StackLayout também define o x:DataType atributo como o tipo viewmodel, indicando que todas as expressões de associação na hierarquia de exibição raiz StackLayout serão compiladas. Isso pode ser verificado alterando qualquer uma das expressões de associação para associar a uma propriedade viewmodel inexistente, o que resultará em um erro de build. Embora este exemplo defina o x:DataType atributo como um literal de cadeia de caracteres, ele também pode ser definido como um tipo com a x:Type extensão de marcação. Para obter mais informações sobre a x:Type extensão de marcação, consulte Extensão de marcação x:Type.

Importante

O atributo x:DataType pode ser redefinido em qualquer ponto de uma hierarquia de exibição.

Os BoxViewelementos , Label e Slider exibições herdam o contexto de associação do StackLayout. Esses modos de exibição são todos destinos de associação que fazem referência às propriedades de origem no viewmodel. Para a BoxView.Color propriedade e a Label.Text propriedade , as associações de dados são OneWay – as propriedades na exibição são definidas a partir das propriedades no viewmodel. No entanto, a propriedade Slider.Value usa uma associação TwoWay. Isso permite que cada Slider um seja definido do viewmodel e também para que o viewmodel seja definido de cada Slider.

Quando o aplicativo é executado pela primeira vez, os BoxViewelementos , Label e Slider são todos definidos do viewmodel com base na propriedade inicial Color definida quando o viewmodel foi instanciado. Isso é mostrado nas seguintes capturas de tela:

Seletor de Cor Compilado Seletor de

Conforme os controles deslizantes são manipulados, os elementos BoxView e Label são atualizados.

Para obter mais informações sobre o seletor de cores, confira ViewModels e notificações de alteração de propriedade.

Usar associações compiladas em um DataTemplate

Associações em um DataTemplate são interpretadas no contexto do objeto que está sendo modelado. Portanto, ao usar associações compiladas em um DataTemplate, o DataTemplate precisa declarar o tipo de seu objeto de dados usando o atributo x:DataType.

A página Lista de Cores Compilada demonstra como usar associações compiladas em um DataTemplate:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:DataBindingDemos"
             x:Class="DataBindingDemos.CompiledColorListPage"
             Title="Compiled Color List">
    <Grid>
        ...
        <ListView x:Name="colorListView"
                  ItemsSource="{x:Static local:NamedColor.All}"
                  ... >
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="local:NamedColor">
                    <ViewCell>
                        <StackLayout Orientation="Horizontal">
                            <BoxView Color="{Binding Color}"
                                     ... />
                            <Label Text="{Binding FriendlyName}"
                                   ... />
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <!-- The BoxView doesn't use compiled bindings -->
        <BoxView Color="{Binding Source={x:Reference colorListView}, Path=SelectedItem.Color}"
                 ... />
    </Grid>
</ContentPage>

A propriedade ListView.ItemsSource é definida como a propriedade estática NamedColor.All. A classe NamedColor usa a reflexão do .NET para enumerar todos os campos públicos estáticos na estrutura Color e armazená-los com seus nomes em uma coleção acessível na propriedade estática All. Portanto, o ListView é preenchido com todas as instâncias de NamedColor. Para cada item em ListView, o contexto de associação para o item é definido como um objeto NamedColor. Os elementos BoxView e Label no ViewCell estão associados às propriedades em NamedColor.

Observe que o DataTemplate define o atributo x:DataType como o tipo NamedColor, indicando que as expressões de associação na hierarquia de exibição DataTemplate serão compiladas. Isso pode ser verificado alterando qualquer uma das expressões de associação para se associar a uma propriedade NamedColor inexistente, o que causará um erro de build. Embora este exemplo defina o x:DataType atributo como um literal de cadeia de caracteres, ele também pode ser definido como um tipo com a x:Type extensão de marcação. Para obter mais informações sobre a x:Type extensão de marcação, consulte Extensão de marcação x:Type.

Quando o aplicativo é executado pela primeira vez, o ListView é preenchido com instâncias de NamedColor. Quando um item no ListView é selecionado, a propriedade BoxView.Color é definida como a cor do item selecionado no ListView:

de cores compiladas lista de cores compiladas lista de

Selecionar outros itens no ListView atualiza a cor do BoxView.

Combinar associações compiladas com associações clássicas

Expressões de associação são compiladas apenas para a hierarquia de exibição em que o atributo x:DataType está definido. Por outro lado, exibições em uma hierarquia na qual o atributo x:DataType não está definido usarão associações clássicas. Portanto, é possível combinar associações compiladas e associações clássicas em uma página. Por exemplo, na seção anterior, os modos de exibição dentro do DataTemplate usam associações compiladas, enquanto o BoxView definido como a cor selecionada no ListView não faz isso.

Estruturar cuidadosamente os atributos x:DataType, portanto, pode levar a uma página que usa associações compiladas e clássicas. Como alternativa, o atributo x:DataType pode ser redefinido a qualquer momento em uma hierarquia de exibição como null usando a extensão de marcação x:Null. Fazer isso indica que qualquer expressão de associação de dentro da hierarquia de exibição usará associações clássicas. A página Associações Mistas demonstra essa abordagem:

<StackLayout x:DataType="local:HslColorViewModel">
    <StackLayout.BindingContext>
        <local:HslColorViewModel Color="Sienna" />
    </StackLayout.BindingContext>
    <BoxView Color="{Binding Color}"
             VerticalOptions="FillAndExpand" />
    <StackLayout x:DataType="{x:Null}"
                 Margin="10, 0">
        <Label Text="{Binding Name}" />
        <Slider Value="{Binding Hue}" />
        <Label Text="{Binding Hue, StringFormat='Hue = {0:F2}'}" />
        <Slider Value="{Binding Saturation}" />
        <Label Text="{Binding Saturation, StringFormat='Saturation = {0:F2}'}" />
        <Slider Value="{Binding Luminosity}" />
        <Label Text="{Binding Luminosity, StringFormat='Luminosity = {0:F2}'}" />
    </StackLayout>
</StackLayout>   

O StackLayout raiz define o atributo x:DataType como o tipo HslColorViewModel, indicando que as expressões de associação na hierarquia de exibição StackLayout raiz serão compiladas. No entanto, o StackLayout interno redefine o atributo x:DataType como null com a expressão de marcação x:Null. Portanto, as expressões de associação no StackLayout interno usam associações clássicas. Somente o BoxView, dentro da hierarquia de exibição StackLayout raiz, usa associações compiladas.

Para obter mais informações sobre a expressão de marcação x:Null, confira Extensão de marcação x:Null.

Desempenho

Associações compiladas melhoram o desempenho da associação de dados, com benefícios de desempenho variáveis. Testes de unidade revelam que:

  • Uma associação compilada que usa notificação de alteração de propriedade (ou seja, uma associação OneWay, OneWayToSource ou TwoWay) é resolvida aproximadamente oito vezes mais rápido do que uma associação clássica.
  • Uma associação compilada que não usa notificação de alteração de propriedade (ou seja, uma associação OneTime) é resolvida aproximadamente vinte vezes mais rápido do que uma associação clássica.
  • Definir o BindingContext em uma associação compilada que usa notificação de alteração de propriedade (ou seja, uma associação OneWay, OneWayToSource ou TwoWay) é aproximadamente cinco vezes mais rápido do que definir o BindingContext em uma associação clássica.
  • Definir o BindingContext em uma associação compilada que não usa notificação de alteração de propriedade (ou seja, uma associação OneTime), é aproximadamente sete vezes mais rápido do que definir o BindingContext em uma associação clássica.

Essas diferenças de desempenho podem aumentar em dispositivos móveis, dependendo da plataforma usada, da versão do sistema operacional usado e do dispositivo no qual o aplicativo está em execução.