Partilhar via


Xamarin.Forms Caminho de associação

Em todos os exemplos anteriores de associação de dados, a propriedade Path da classe Binding (ou a propriedade Path da extensão de marcação Binding) foi definida como uma única propriedade. Na verdade, é possível definir Path como uma subpropriedade (uma propriedade de uma propriedade) ou como um membro de uma coleção.

Por exemplo, suponha que a página contenha um TimePicker:

<TimePicker x:Name="timePicker">

A propriedade Time de TimePicker é do tipo TimeSpan, mas talvez você deseje criar uma associação de dados que referencie a propriedade TotalSeconds desse valor TimeSpan. Esta é a associação de dados:

{Binding Source={x:Reference timePicker},
         Path=Time.TotalSeconds}

A propriedade Time é do tipo TimeSpan, que tem uma propriedade TotalSeconds. As propriedades Time e TotalSeconds são simplesmente conectadas com um ponto. Os itens da cadeia de caracteres Path sempre se referem a propriedades e não aos tipos dessas propriedades.

Esse exemplo e vários outros são mostrados na página Variações de caminho:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:globe="clr-namespace:System.Globalization;assembly=netstandard"
             x:Class="DataBindingDemos.PathVariationsPage"
             Title="Path Variations"
             x:Name="page">
    <ContentPage.Resources>
        <ResourceDictionary>
            <Style TargetType="Label">
                <Setter Property="FontSize" Value="Large" />
                <Setter Property="HorizontalTextAlignment" Value="Center" />
                <Setter Property="VerticalOptions" Value="CenterAndExpand" />
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>

    <StackLayout Margin="10, 0">
        <TimePicker x:Name="timePicker" />

        <Label Text="{Binding Source={x:Reference timePicker},
                              Path=Time.TotalSeconds,
                              StringFormat='{0} total seconds'}" />

        <Label Text="{Binding Source={x:Reference page},
                              Path=Content.Children.Count,
                              StringFormat='There are {0} children in this StackLayout'}" />

        <Label Text="{Binding Source={x:Static globe:CultureInfo.CurrentCulture},
                              Path=DateTimeFormat.DayNames[3],
                              StringFormat='The middle day of the week is {0}'}" />

        <Label>
            <Label.Text>
                <Binding Path="DateTimeFormat.DayNames[3]"
                         StringFormat="The middle day of the week in France is {0}">
                    <Binding.Source>
                        <globe:CultureInfo>
                            <x:Arguments>
                                <x:String>fr-FR</x:String>
                            </x:Arguments>
                        </globe:CultureInfo>
                    </Binding.Source>
                </Binding>
            </Label.Text>
        </Label>

        <Label Text="{Binding Source={x:Reference page},
                              Path=Content.Children[1].Text.Length,
                              StringFormat='The second Label has {0} characters'}" />
    </StackLayout>
</ContentPage>

No segundo Label, a origem da associação é a página propriamente dita. A propriedade Content é do tipo StackLayout, que tem uma propriedade Children do tipo IList<View>, que, por sua vez, tem uma propriedade Count que indica o número de filhos.

Caminhos com indexadores

A associação no terceiro Label nas páginas Variações de caminho referencia a classe CultureInfo no namespace System.Globalization:

<Label Text="{Binding Source={x:Static globe:CultureInfo.CurrentCulture},
                      Path=DateTimeFormat.DayNames[3],
                      StringFormat='The middle day of the week is {0}'}" />

A origem é definida como a propriedade estática CultureInfo.CurrentCulture, que é um objeto do tipo CultureInfo. Esse classe define uma propriedade chamada DateTimeFormat do tipo DateTimeFormatInfo que contém uma coleção DayNames. O índice seleciona o quarto item.

O quarto Label faz algo similar, mas para a cultura associada à França. A propriedade Source da associação é definida como o objeto CultureInfo com um construtor:

<Label>
    <Label.Text>
        <Binding Path="DateTimeFormat.DayNames[3]"
                 StringFormat="The middle day of the week in France is {0}">
            <Binding.Source>
                <globe:CultureInfo>
                    <x:Arguments>
                        <x:String>fr-FR</x:String>
                    </x:Arguments>
                </globe:CultureInfo>
            </Binding.Source>
        </Binding>
    </Label.Text>
</Label>

Confira Passando argumentos de construtor para obter mais detalhes sobre como especificar argumentos de construtor em XAML.

Por fim, o último exemplo é semelhante ao segundo, exceto que ele referencia um dos filhos do StackLayout:

<Label Text="{Binding Source={x:Reference page},
                      Path=Content.Children[1].Text.Length,
                      StringFormat='The first Label has {0} characters'}" />

Esse filho é um Label, que tem uma propriedade Text do tipo String, que, por sua vez, tem uma propriedade Length. O primeiro Label relata o TimeSpan definido no TimePicker; portanto, quando esse texto é alterado, o último Label também é alterado.

Este é o programa em execução:

Variações de caminho

Caminhos complexos de depuração

Definições de caminhos complexos podem ser difíceis de serem construídas: você precisa saber o tipo de cada subpropriedade ou o tipo dos itens na coleção para adicionar corretamente a próxima subpropriedade, mas os tipos propriamente ditos não são exibidos no caminho. Uma boa técnica é criar o caminho de forma incremental e examinar os resultados intermediários. Para esse último exemplo, você pode começar sem nenhuma definição de Path:

<Label Text="{Binding Source={x:Reference page},
                      StringFormat='{0}'}" />

Isso exibe o tipo da origem da associação ou DataBindingDemos.PathVariationsPage. Você sabe que PathVariationsPage deriva de ContentPage e, portanto, ele tem uma propriedade Content:

<Label Text="{Binding Source={x:Reference page},
                      Path=Content,
                      StringFormat='{0}'}" />

O tipo da propriedade Content agora é revelado como sendo Xamarin.Forms.StackLayout. Adicione a Children propriedade ao Path e o tipo é Xamarin.Forms.ElementCollection'1[Xamarin.Forms.View], que é uma classe interna a Xamarin.Forms, mas obviamente um tipo de coleção. Adicione um índice a ele e o tipo será Xamarin.Forms.Label. Continue dessa maneira.

À medida Xamarin.Forms que processa o caminho de associação, ele instala um PropertyChanged manipulador em qualquer objeto no caminho que implementa a INotifyPropertyChanged interface. Por exemplo, a associação final reage a uma alteração no primeiro Label porque a propriedade Text é alterada.

Se uma propriedade no caminho de associação não implementar INotifyPropertyChanged, todas as alterações a essa propriedade serão ignoradas. Algumas alterações podem invalidar por completo o caminho de associação. Portanto, você deverá usar essa técnica somente quando a cadeia de caracteres de propriedades e subpropriedades nunca se tornarem inválidas.