Usare i data binding in XAML
I data binding possono essere dichiarati nel codice o in XAML usando estensioni di markup. Questa unità illustra quest'ultimo approccio, perché è il modo più comune per creare binding. La scelta del linguaggio XAML è dettata da due motivi. In primo luogo, i binding vengono in genere considerati come parte del codice dell'interfaccia utente poiché ottengono i dati per la visualizzazione di tale interfaccia. In secondo luogo, è disponibile un'estensione di markup denominata Binding
che semplifica questa operazione.
Che cosa sono i data binding
Un binding consiste nell'associazione di due proprietà. Una si trova nell'interfaccia utente e l'altra nell'oggetto del modello di dati. Se il valore di una delle proprietà viene modificato, l'oggetto di binding può aggiornare il valore dell'altra. In altre parole, i binding sono oggetti con il ruolo di intermediari che eseguono la sincronizzazione dell'interfaccia utente e dei dati. Per identificare i due oggetti interessati, vengono usati i termini origine e destinazione:
Origine: può essere costituita da un oggetto di qualsiasi tipo. In pratica, come origine dati si usa in genere un oggetto dati. Per l'oggetto di origine è necessario identificare la proprietà per la partecipazione al binding. Per identificare la proprietà, si imposta la proprietà
Path
nel binding.Destinazione: La destinazione è una proprietà implementata usando una proprietà speciale denominata
BindableProperty
. L'oggetto conBindableProperty
deve derivare daBindableObject
. Tutti i controlli forniti in .NET MAUI derivano daBindableObject
e la maggior parte delle relative proprietà èBindableProperties
.
Il diagramma seguente illustra il modo in cui il binding costituisce un oggetto intermedio tra due proprietà:
Come creare un data binding in XAML
Si esaminerà ora un semplice esempio di binding creato in XAML tramite l'estensione di markup {Binding}
. In questo esempio viene definito il binding tra la proprietà WeatherService.Humidity
dell'origine e la proprietà Text
del controllo dell'interfaccia utente.
<VerticalStackLayout Margin="10">
<VerticalStackLayout.Resources>
<ResourceDictionary>
<services:WeatherService x:Key="myWeatherService" />
</ResourceDictionary>
</VerticalStackLayout.Resources>
<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" />
</VerticalStackLayout>
L'origine di associazione è:
Un'istanza dell'oggetto del tipo
WeatherService
. Viene fatto riferimento all'istanza tramite l'estensione XAML{StaticResource ...}
, che punta a un oggetto nel dizionario risorse del layout dello stack.Path
punta a una proprietà denominataHumidity
nel tipoWeatherService
.Path
è il primo parametro senza nome nella sintassi{Binding}
e la sintassiPath=
può essere omessa. Questi due binding sono equivalenti:<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" /> <Label Text="{Binding Humidity, Source={StaticResource myWeatherService}}" />
La destinazione del binding è:
- Il controllo
Label
. - Proprietà
Text
del controllo.
Quando viene visualizzata l'interfaccia utente, l'estensione XAML {Binding}
crea un binding tra WeatherService
e Label
. Il binding legge il valore della proprietà WeatherService.Humidity
nella proprietà Label.Text
.
Usare un altro controllo come origine di associazione
Una funzionalità utile del binding è la possibilità di eseguire il binding ad altri controlli. Il codice XAML seguente è una semplice dimostrazione:
<VerticalStackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Label x:Name="TargetLabel" Text="TEXT TO ROTATE" BackgroundColor="Yellow" />
<Slider WidthRequest="100" Maximum="360"
Value="{Binding Rotation, Mode=OneWayToSource, Source={x:Reference TargetLabel}}" />
</VerticalStackLayout>
La proprietà Slider.Value
è associata alla proprietà Label.Rotation
, ma in modo diverso rispetto a quanto spiegato in precedenza. Questa proprietà usa la modalità di associazione OneWayToSource
, che inverte il meccanismo di associazione tipico. Invece dell'Origine che aggiorna la Destinazione, OneWayToSource
aggiorna l'Origine quando la Destinazione cambia. In questo esempio quando il dispositivo di scorrimento si sposta, viene aggiornata la rotazione dell'etichetta in base al valore del dispositivo di scorrimento, come illustrato nell'animazione seguente:
Lo scenario tipico per il binding di controlli l'uno all'altro è costituito dai casi in cui un controllo, in genere un controllo raccolta, ad esempio ListView
o CarouselView
, include un elemento selezionato che si vuole usare come origine dati. Nell'esempio di una pagina che visualizza le previsioni meteo, potrebbe essere presente un elemento ListView
che presenta una previsione di cinque giorni. Quando l'utente seleziona un giorno nell'elenco, i dettagli delle previsioni meteo vengono visualizzati in altri controlli. Se l'utente seleziona un altro giorno, gli altri controlli vengono aggiornati di nuovo con i dettagli del giorno selezionato.
Usare la stessa origine per più binding
L'esempio precedente ha illustrato l'uso di una risorsa statica come origine per un singolo binding. Tale origine può essere usata in più binding. Di seguito è riportato un esempio di dichiarazione di un binding tra tre controlli diversi, tutti associati allo stesso oggetto e proprietà Path
, anche se alcuni omettono la proprietà Path
:
<VerticalStackLayout Margin="10">
<VerticalStackLayout.Resources>
<vm:SimpleWeatherServiceObject x:Key="myWeatherService" />
</VerticalStackLayout.Resources>
<Entry Text="{Binding Humidity, Source={StaticResource myWeatherService}}" />
<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" />
</VerticalStackLayout>
Non è necessario usare lo stesso Path
quando si usa lo stesso Source
:
<VerticalStackLayout Margin="10">
<VerticalStackLayout.Resources>
<vm:SimpleWeatherServiceObject x:Key="myWeatherService" />
</VerticalStackLayout.Resources>
<Entry Text="{Binding Temperature, Source={StaticResource myWeatherService}}" />
<Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" />
</VerticalStackLayout>
Raramente si presenta un singolo dato da un'origine, anche se può verificarsi. In genere sono disponibili diversi controlli che usano dati diversi dalla stessa origine. Questa situazione è così comune che la classe BindableObject
ha una proprietà denominata BindingContext
che funziona come origine per il data binding. Tenere presente che i controlli di .NET MAUI ereditano dalla classe BindableObject
, pertanto i controlli di .NET MAUI hanno la proprietà BindingContext
.
L'impostazione di Source
del binding è facoltativa. Un binding che non ha Source
impostato cerca automaticamente BindingContext
nella struttura ad albero visuale XAML. Questo valore è impostato in XAML o assegnato a un elemento padre in base al codice. I binding vengono valutati seguendo questo modello:
Se il binding definisce
Source
, tale origine viene usata e la ricerca si arresta.Path
del binding viene applicato aSource
per ottenere un valore. SeSource
non è impostato, inizia la ricerca per un'origine di associazione.La ricerca inizia con l'oggetto di destinazione stesso. Se
BindingContext
dell'oggetto di destinazione non è Null, la ricerca si arresta ePath
del binding viene applicato aBindingContext
per ottenere un valore. SeBindingContext
è Null, la ricerca continua.Questo processo continua finché non viene raggiunta la radice XAML. La ricerca termina controllando
BindingContext
della radice per verificare se è presente un valore non Null. Se non è stato trovato alcunBindingContext
valido, il binding non ha alcun elemento a cui associarsi e non esegue alcuna operazione.
BindingContext
viene comunemente impostato a livello dell'oggetto radice, in modo da essere applicato all'intero codice XAML.
Esiste un'ultima funzionalità interessante che vale la pena di indicare. I binding controllano se sono state apportate modifiche al riferimento all'oggetto della loro origine. Questo approccio funziona anche per i binding che usano BindingContext
come origine. Se la proprietà Source
o BindingContext
viene riassegnata a un altro oggetto, i binding recuperano i dati dalla nuova origine e aggiornano la destinazione.