Xamarin.Forms Associações compiladas
As associações compiladas são resolvidas mais rapidamente do que as associações clássicas, melhorando assim o desempenho da ligação de dados em Xamarin.Forms aplicativos.
Associações de dados têm dois problemas principais:
- 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.
- 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 é:
- Habilitar a compilação de XAML. Para obter mais informações sobre a compilação de XAML, confira Compilação de XAML.
- Definir um atributo
x:DataType
em umVisualElement
como o tipo do objeto ao qualVisualElement
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 localização de uma hierarquia de exibição.
Para usar associações compiladas, o atributo x:DataType
deve ser definido como um literal de cadeia de caracteres ou um tipo usando a extensão de marcação x:Type
. 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 cores compilado demonstra o uso de associações compiladas entre Xamarin.Forms exibições e propriedades do modelo de exibição:
<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 se associar a uma propriedade viewmodel inexistente, o que causará um erro de build. Embora este exemplo defina o atributo x:DataType
como um literal de cadeia de caracteres, ele também pode ser definido como um tipo com a extensão de marcação x:Type
. Para mais informações sobre a extensão de marcação x:Type
, 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 elementos BoxView
, Label
e as exibições Slider
herdam o contexto de associação da StackLayout
. Essas exibições são destinos de associação que referenciam as propriedades de origem no viewmodel. Para as propriedades BoxView.Color
e Label.Text
, as associações de dados são OneWay
– as propriedades na exibição são definidas nas propriedades do viewmodel. No entanto, a propriedade Slider.Value
usa uma associação TwoWay
. Isso permite que cada Slider
seja definido no viewmodel e também que o viewmodel seja definido em cada Slider
.
Quando o aplicativo é executado pela primeira vez, os elementos , e os BoxView
elementos são todos definidos a partir do viewmodel com base na propriedade inicial Color
definida quando o viewmodel foi instanciadoSlider
. Label
Isso é mostrado nas seguintes capturas de tela:
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.
Uso de 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 atributo x:DataType
como um literal de cadeia de caracteres, ele também pode ser definido como um tipo com a extensão de marcação x:Type
. Para mais informações sobre a extensão de marcação x:Type
, 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
:
Selecionar outros itens no ListView
atualiza a cor do BoxView
.
Combinar associações compiladas a 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
ouTwoWay
) é 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çãoOneWay
,OneWayToSource
ouTwoWay
) é aproximadamente cinco vezes mais rápido do que definir oBindingContext
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çãoOneTime
), é aproximadamente sete vezes mais rápido do que definir oBindingContext
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.