Condividi tramite


Associazioni compilate

Sfogliare l'esempio. Esplorare l'esempio

I data binding dell'interfaccia utente dell'app multipiattaforma .NET (.NET MAUI) presentano due problemi principali:

  1. Non è prevista la convalida in fase di compilazione delle espressioni di binding. I binding vengono invece risolti in fase di runtime. Di conseguenza tutti i binding non validi non vengono rilevati fino alla fase di runtime, quando l'applicazione non si comporta come previsto o vengono visualizzati messaggi di errore.
  2. Non sono efficienti a livelli di costi. I binding vengono risolti in fase di runtime mediante l'ispezione oggetti di carattere generale (reflection) e il carico di lavoro necessario varia a seconda della piattaforma.

Le associazioni compilate migliorano le prestazioni del data binding nelle applicazioni MAUI .NET risolvendo le espressioni di associazione in fase di compilazione anziché in fase di esecuzione. Questa convalida delle espressioni di binding in fase di compilazione consente anche agli sviluppatori una risoluzione dei problemi più agevole, perché i binding non validi vengono segnalati come errori di compilazione.

Per utilizzare le associazioni compilate, impostare un x:DataType attributo su un VisualElement sul tipo dell'oggetto a cui VisualElement verrà associato e ai relativi elementi figlio. È consigliabile impostare l'attributo x:DataType sullo stesso livello della gerarchia di visualizzazione sul quale è impostato BindingContext. Tuttavia, questo attributo può essere ridefinito in qualsiasi posizione in una gerarchia di visualizzazione.

Nota

Le associazioni compilate richiedono l'uso della compilazione XAML, abilitata per impostazione predefinita in .NET MAUI. Se hai disabilitato la compilazione XAML, dovrai abilitarla. Per altre informazioni, vedere XAML Compilation (Compilazione XAML).

Per usare le associazioni compilate, l'attributo x:DataType deve essere impostato su un valore letterale stringa o su un tipo usando l'estensione di x:Type markup. In fase di compilazione XAML, le espressioni di binding non valide vengono segnalate come errori di compilazione. Tuttavia il compilatore XAML segnala un errore di compilazione solo per la prima espressione di binding non valida rilevata. Tutte le espressioni di binding valido definite in VisualElement o negli elementi figlio verranno compilate, indipendentemente dal fatto che BindingContext sia impostato in XAML o nel codice. La compilazione di un'espressione di binding genera codice compilato che ottiene un valore da una proprietà in sourcee lo imposta sulla proprietà in target specificata nel markup. Inoltre a seconda dell'espressione di binding il codice generato potrebbe rilevare modifiche nel valore della proprietà source e aggiornare la proprietà target, nonché eseguire il push delle modifiche dalla proprietà target alla proprietà source.

Importante

Le associazioni compilate sono disabilitate per tutte le espressioni di associazione che definiscono la Source proprietà . Il motivo è che la proprietà Source viene sempre impostata usando l'estensione di markup x:Reference, che non può essere risolta in fase di compilazione.

Inoltre, le associazioni compilate non sono attualmente supportate in più associazioni.

Per impostazione predefinita, .NET MAUI non genera avvisi di compilazione per le associazioni che non usano associazioni compilate, a meno che non sia stato abilitato NativeAOT per l'app. Tuttavia, puoi acconsentire esplicitamente agli avvisi di binding compilati generati impostando la proprietà di $(MauiStrictXamlCompilation) compilazione su true nel file di progetto dell'app (*.csproj):

<MauiStrictXamlCompilation>true</MauiStrictXamlCompilation>

Usare binding compilati

L'esempio seguente illustra l'uso di associazioni compilate tra le viste MAUI .NET e le proprietà del modello di visualizzazione:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:DataBindingDemos"
             x:Class="DataBindingDemos.CompiledColorSelectorPage"
             x:DataType="local:HslColorViewModel"
             Title="Compiled Color Selector">
    <ContentPage.BindingContext>
        <local:HslColorViewModel Color="Sienna" />
    </ContentPage.BindingContext>
    ...
    <StackLayout>
        <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>

Crea ContentPage un'istanza di HslColorViewModel e inizializza la Color proprietà all'interno dei tag dell'elemento proprietà per la BindingContext proprietà . Definisce ContentPage anche l'attributo x:DataType come tipo viewmodel, che indica che tutte le espressioni di associazione nella gerarchia di ContentPage visualizzazione verranno compilate. Questa operazione può essere verificata modificando una qualsiasi delle espressioni di associazione da associare a una proprietà viewmodel inesistente, che genererà un errore di compilazione. Anche se questo esempio imposta l'attributo x:DataType su un valore letterale stringa, può anche essere impostato su un tipo con l'estensione x:Type di markup. Per altre informazioni sull'estensione x:Type di markup, vedere estensione di markup x:Type.

Importante

L'attributo x:DataType può essere ridefinito in qualsiasi posizione di una gerarchia di visualizzazione.

Gli elementi BoxView e Label e le viste Slider ereditano il contesto di binding da ContentPage. Queste viste sono tutte destinazioni di associazione che fanno riferimento alle proprietà di origine nel modello di visualizzazione. Per la BoxView.Color proprietà e la Label.Text proprietà , i data binding sono OneWay : le proprietà nella visualizzazione vengono impostate dalle proprietà nel modello di visualizzazione. Tuttavia la proprietà Slider.Value usa un binding TwoWay. In questo modo ogni Slider elemento può essere impostato dal modello di visualizzazione e anche per impostare il modello di visualizzazione da ogni Slideroggetto .

Quando l'esempio viene eseguito per la prima volta, gli BoxViewelementi , Label e Slider gli elementi vengono impostati dal modello di visualizzazione in base alla proprietà iniziale Color impostata quando è stata creata un'istanza del modello di visualizzazione. Man mano che i dispositivi di scorrimento vengono modificati, gli BoxView elementi e Label vengono aggiornati di conseguenza:

Selettore colori compilato.

Per altre informazioni su questo selettore di colori, vedere ViewModels e property-change notifications.

Usare associazioni compilate in un oggetto DataTemplate

I binding in un DataTemplate sono interpretati nel contesto dell'oggetto basato su modelli. Pertanto quando si usano binding compilati in un DataTemplate, DataTemplate deve dichiarare il tipo del relativo oggetto dati usando l'attributo x:DataType.

L'esempio seguente illustra l'uso di associazioni compilate in un DataTemplateoggetto :

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             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>

La proprietà ListView.ItemsSource è impostata sulla proprietà NamedColor.All statica. La NamedColor classe usa la reflection .NET per enumerare tutti i campi pubblici statici nella Colors classe e archiviarli con i relativi nomi in una raccolta accessibile dalla proprietà statica All . Di conseguenza l'elemento ListView viene riempito con tutte le istanze NamedColor. Per ogni elemento in ListView il contesto di binding per l'elemento è impostato su un oggetto NamedColor. Gli elementi BoxView e Label in ViewCell sono associati a proprietà NamedColor.

DataTemplate Definisce l'attributo x:DataType come NamedColor tipo, a indicare che tutte le espressioni di associazione nella gerarchia di DataTemplate visualizzazione verranno compilate. È possibile verificare questa impostazione modificando le espressioni di binding per impostare il binding a una proprietà NamedColor inesistente, che produrrà un errore di compilazione. Anche se questo esempio imposta l'attributo x:DataType su un valore letterale stringa, può anche essere impostato su un tipo con l'estensione x:Type di markup. Per altre informazioni sull'estensione x:Type di markup, vedere estensione di markup x:Type.

Quando l'esempio viene eseguito per la prima volta, l'oggetto ListView viene popolato con NamedColor le istanze di . Quando viene selezionato un elemento in ListView, la proprietà BoxView.Color viene impostata sul colore dell'elemento selezionato in ListView:

Elenco colori compilato.

Se si selezionano altri elementi in ListView viene aggiornato il colore di BoxView.

Combinare associazioni compilate con associazioni classiche

Le espressioni di binding vengono compilate solo per la gerarchia di visualizzazione in cui è definito l'attributo x:DataType. Al contrario, tutte le viste in una gerarchia in cui l'attributo x:DataType non è definito usa i binding classici. È pertanto possibile combinare binding compilati e classici in una pagina. Ad esempio nella sezione precedente le viste in DataTemplate usano i binding compilati, mentre l'elemento BoxView impostato sul colore selezionato in ListView non usa tali binding.

Un'attenta strutturazione degli attributi x:DataType può dare origine a una pagina che usa binding sia compilati che classici. In alternativa l'attributo x:DataType può essere ridefinito in qualsiasi punto di una gerarchia di visualizzazione come null usando l'estensione di markup x:Null. Questa operazione indica che tutte le espressioni di binding all'interno della gerarchia di visualizzazione useranno i binding classici. L'esempio seguente illustra questo approccio:

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

L'elemento radice StackLayout definisce l'attributo x:DataType come tipo HslColorViewModel, a indicare che tutte le espressioni di binding nella gerarchia di visualizzazione radice StackLayout verranno compilate. Tuttavia l'elemento StackLayout interno ridefinisce l'attributo x:DataType come null con l'espressione di markup x:Null. Di conseguenza le espressioni di binding nell'elemento StackLayout interno usano i binding classici. Solo BoxView nell'ambito della gerarchia di visualizzazione radice StackLayout usa i binding compilati.

Per altre informazioni sull'espressione di markup x:Null, vedere Estensione di markup x:Null.

Prestazioni

Le associazioni compilate migliorano le prestazioni del data binding, con il vantaggio delle prestazioni variabile:

  • Un binding compilato che usa la notifica di modifica delle proprietà (ovvero un binding OneWay, OneWayToSource o TwoWay) viene risolto circa 8 volte più rapidamente rispetto a un binding classico.
  • Un binding compilato che non usa la notifica di modifica delle proprietà (ovvero un binding OneTime) viene risolto circa 20 volte più rapidamente rispetto a un binding classico.
  • L'impostazione di BindingContext per un binding compilato che usa la notifica di modifica delle proprietà (ovvero un binding OneWay, OneWayToSource o TwoWay) è circa 5 volte più rapida rispetto all'impostazione di BindingContext per un binding classico.
  • L'impostazione di BindingContext per un binding compilato che non usa la notifica di modifica delle proprietà (ovvero un binding OneTime) è circa 7 volte più rapida rispetto all'impostazione di BindingContext per un binding classico.

Queste variazioni di prestazioni possono risultare più importanti nei dispositivi mobili a seconda della piattaforma usata, della versione del sistema operativo e del dispositivo in cui viene eseguita l'applicazione.