Xamarin.Forms Percorso di associazione

Download Sample Scaricare l'esempio

In tutti gli esempi di data binding precedenti, la proprietà Path della classe Binding (o la proprietà Path dell'estensione di markup Binding) è stata impostata su una singola proprietà. È in effetti possibile impostare Path su una proprietà secondaria (una proprietà di una proprietà) o su un membro di una raccolta.

Ad esempio, si supponga che la pagina contenga un controllo TimePicker:

<TimePicker x:Name="timePicker">

La proprietà Time di TimePicker è di tipo TimeSpan, ma si potrebbe voler creare un data binding che fa riferimento alla proprietà TotalSeconds di tale valore TimeSpan. Ecco il data binding:

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

La proprietà Time è di tipo TimeSpan, che ha una proprietà TotalSeconds. Le proprietà Time e TotalSeconds sono semplicemente collegate tramite un punto. Gli elementi nella stringa Path fanno sempre riferimento alle proprietà e non ai tipi di queste proprietà.

Questo esempio e vari altri sono disponibili nella pagina Path Variations:

<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>

Nella seconda Label, l'origine del binding è la pagina stessa. La proprietà Content è di tipo StackLayout, che ha una proprietà Children di tipo IList<View>, che ha una proprietà Count che indica il numero di elementi figlio.

Percorsi con indicizzatori

Il binding nella terza Label nella pagina Path Variations fa riferimento alla classe CultureInfo nello spazio dei nomi System.Globalization:

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

L'origine è impostata sulla proprietà statica CultureInfo.CurrentCulture, ovvero un oggetto di tipo CultureInfo. Tale classe definisce una proprietà denominata DateTimeFormat di tipo DateTimeFormatInfo che contiene una raccolta DayNames. L'indice seleziona il quarto elemento.

La quarta Label esegue un'operazione simile ma per le impostazioni cultura associato alla Francia. La proprietà Source del binding viene impostata sull'oggetto CultureInfo con un costruttore:

<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>

Vedere Passaggio degli argomenti del costruttore per altri dettagli su come specificare gli argomenti del costruttore in XAML.

Infine, l'ultimo esempio è simile al secondo, ad eccezione del fatto che fa riferimento a uno degli elementi figlio di StackLayout:

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

Tale elemento figlio è una Label, con una proprietà Text di tipo String, con una proprietà Length. La prima Label indica il valore TimeSpan impostato in TimePicker, pertanto quando cambia il testo, cambia anche la Label finale.

Ecco il programma in esecuzione:

Path Variations

Debug di percorsi complessi

Le definizioni di percorso complesse possono essere difficili da costruire. È necessario conoscere il tipo di ogni proprietà secondaria o il tipo di elementi nella raccolta per aggiungere correttamente la proprietà secondaria successiva, ma i tipi stesso non compaiono nel percorso. Una buona tecnica consiste nel costruire il percorso in modo incrementale ed esaminare i risultati intermedi. Per l'ultimo esempio si potrebbe iniziare senza alcuna definizione di Path:

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

Questo codice visualizza il tipo di origine del binding, o DataBindingDemos.PathVariationsPage. Si sa che PathVariationsPage deriva da ContentPage, quindi ha una proprietà Content:

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

Il tipo della proprietà Content è ora noto ed è Xamarin.Forms.StackLayout. Aggiungere la Children proprietà a Path e il tipo è Xamarin.Forms.ElementCollection'1[Xamarin.Forms.View], ovvero una classe interna a Xamarin.Forms, ma ovviamente un tipo di raccolta. Aggiungere un indice e il tipo è Xamarin.Forms.Label. Continuare in questo modo.

Durante Xamarin.Forms l'elaborazione del percorso di associazione, installa un PropertyChanged gestore in qualsiasi oggetto nel percorso che implementa l'interfaccia INotifyPropertyChanged . Ad esempio, il binding finale reagisce a una modifica nella prima Label perché cambia la proprietà Text.

Se una proprietà nel percorso di binding non implementa INotifyPropertyChanged, eventuali modifiche a tale proprietà verranno ignorate. Alcune modifiche potrebbero invalidare del tutto il percorso di binding, quindi è consigliabile usare questa tecnica solo quando la stringa di proprietà e proprietà secondarie non diventa mai non valida.