Kompilierte Bindungen in Xamarin.Forms

Download Sample Das Beispiel herunterladen

Kompilierte Bindungen werden schneller aufgelöst als klassische, wodurch die Leistung der Datenbindung in Xamarin.Forms-Anwendungen verbessert wird.

Datenbindungen weisen zwei Hauptprobleme auf:

  1. Es gibt keine Validierung von Bindungsausdrücken zur Kompilierzeit. Stattdessen werden Bindungen zur Laufzeit aufgelöst. Daher werden ungültige Bindungen erst zur Laufzeit ermittelt, wenn die Anwendung nicht erwartungsgemäß funktioniert oder Fehlermeldungen angezeigt werden.
  2. Sie sind nicht kosteneffizient. Bindungen werden zur Laufzeit mithilfe Universeller Objektüberprüfung (Reflektion) aufgelöst. Der durch diese Methode entstehende Mehraufwand variiert von Plattform zu Plattform.

Kompilierte Bindungen verbessern die Datenbindungsleistung in Xamarin.Forms-Anwendungen, indem die Bindungsausdrücke zur Kompilierzeit anstatt zur Laufzeit aufgelöst werden. Darüber hinaus vereinfacht die Validierung von Bindungsausdrücken zur Kompilierzeit die Problembehandlung durch den Entwickler, da ungültige Bindungen als Buildfehler gemeldet werden.

Sie können kompilierte Bindungen wie folgt verwenden:

  1. Aktivieren Sie die XAML-Kompilierung. Weitere Informationen zur XAML-Kompilierung finden Sie unter XAML Compilation (XAML-Kompilierung).
  2. Legen Sie ein x:DataType-Attribut für ein VisualElement auf den Typ des Objekts fest, an das VisualElement und dessen untergeordnete Elemente gebunden werden.

Hinweis

Es wird empfohlen, das x:DataType-Attribut auf der gleichen Ebene in der Ansichtshierarchie festzulegen, auf der die BindingContext-Eigenschaft festgelegt ist. Dieses Attribut kann jedoch an jeder Position in einer Ansichtshierarchie neu definiert werden.

Wenn Sie kompilierte Bindungen verwenden möchten, muss das Attribut x:DataType auf ein Zeichenfolgenliteral oder einen Typ festgelegt sein, der die Markuperweiterung x:Type verwendet. Zur Kompilierzeit des XAML-Codes werden jegliche ungültige Bindungsausdrücke als Buildfehler gemeldet. Der XAML-Compiler meldet einen Buildfehler jedoch nur für den ungültigen Bindungsausdruck, der als erstes ermittelt wird. Alle gültigen Bindungsausdrücke, die im VisualElement-Element oder in dessen untergeordneten Elemente definiert sind, werden unabhängig davon, ob BindingContext in der XAML-Datei oder im Code festgelegt ist, kompiliert. Das Kompilieren eines Bindungsausdrucks generiert kompilierten Code, der einen Wert von einer Eigenschaft in der Quelle abruft und diesen für die Eigenschaft des Ziels festlegt, das im Markup angegeben ist. Je nach Bindungsausdruck wird außerdem der Wert der Eigenschaft source geändert und die Eigenschaft target aktualisiert. Möglicherweise werden Änderungen vom Ziel zurück an die Quelle übertragen.

Wichtig

Kompilierte Bindungen sind derzeit für alle Bindungsausdrücke deaktiviert, die die Source-Eigenschaft definieren. Der Grund dafür ist, dass die Source-Eigenschaft immer mit der Markuperweiterung x:Reference festgelegt wird, die zur Kompilierzeit nicht aufgelöst werden kann.

Verwenden kompilierter Bindungen

Die Seite Compiled Color Selector (Kompilierte Farbauswahl) veranschaulicht die Verwendung von kompilierten Bindungen zwischen Xamarin.Forms-Ansichten und ViewModel-Eigenschaften:

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

Der StackLayout-Stamm instanziiert das HslColorViewModel-Objekt und initialisiert die Color-Eigenschaft innerhalb der Eigenschaftselementtags für die BindingContext-Eigenschaft. Dieser StackLayout-Stamm definiert außerdem das x:DataType-Attribut als ViewModel-Typ, der angibt, dass alle Bindungsausdrücke in der Ansichtshierarchie des StackLayout-Stamms kompiliert werden. Dies können Sie überprüfen, indem Sie einen der Bindungsausdrücke so ändern, dass er an eine nicht vorhandene ViewModel-Eigenschaft gebunden wird. Dies führt zu einem Buildfehler. In diesem Beispiel wird das x:DataType-Attribut auf ein Zeichenfolgenliteral festgelegt. Sie können es jedoch auch auf einen Typ mit der Markuperweiterung x:Type festlegen. Weitere Informationen zur Markuperweiterung x:Type finden Sie unter x:Type-Markuperweiterung.

Wichtig

Das x:DataType-Attribut kann jederzeit in einer Ansichtshierarchie neu definiert werden.

Die BoxView- und Label-Elemente sowie die Slider-Ansichten erben den Bindungskontext von StackLayout. Alle diese Ansichten sind Bindungsziele, die auf Quelleneigenschaften des ViewModels verweisen. Für die Eigenschaften BoxView.Color und Label.Text sind die Datenbindungen OneWay. Die Eigenschaften in der Ansicht werden über die Eigenschaften in der ViewModel-Klasse festgelegt. Die Eigenschaft Slider.Value verwendet jedoch eine TwoWay-Bindung. Dadurch kann jedes Slider-Element über ViewModel und die ViewModel-Klasse über jedes Slider-Element festgelegt werden.

Bei der ersten Ausführung der Anwendung werden alle BoxView-, Label- und Slider-Elemente über die ViewModel-Klasse basierend auf der ursprünglichen Color-Eigenschaft festgelegt, die bei der Instanziierung von ViewModel festgelegt wurde. Dies wird im folgenden Screenshot veranschaulicht:

Compiled Color Selector

Wenn die Schieberegler bewegt werden, werden die Elemente BoxView und Label entsprechend aktualisiert.

Weitere Informationen zu dieser Farbauswahl finden Sie unter ViewModels and Property-Change Notifications (Benachrichtigungen für Änderungen an ViewModels und Eigenschaften).

Verwenden von kompilierten Bindungen in einer DataTemplate-Klasse

Bindungen in einer DataTemplate-Klasse werden abhängig vom Kontext des Objekts interpretiert, auf dem die Vorlage basiert. Daher muss die DataTemplate-Klasse den Typ ihres Datenobjekts mithilfe des x:DataType-Attributs deklarieren, wenn kompilierte Bindungen in einer DataTemplate-Klasse verwendet werden.

Die Seite Compiled Color List (Kompilierte Farbliste) veranschaulicht die Verwendung kompilierter Bindungen in einer DataTemplate-Klasse:

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

Für die Eigenschaft ListView.ItemsSource wird die statische Eigenschaft NamedColor.All festgelegt. Die NamedColor-Klasse nutzt die .NET-Reflektion, um alle statischen öffentlichen Felder in der Color-Struktur aufzuführen und sie mitsamt ihrer Namen in einer Sammlung zu speichern, auf die über die statische Eigenschaft All zugegriffen werden kann. Aus diesem Grund wird ListView mit allen Instanzen von NamedColor aufgefüllt. Der Bindungskontext aller Elemente in der ListView-Klasse wird auf ein NamedColor-Objekt festgelegt. Die Elemente BoxView und Label in der ViewCell-Klasse werden an NamedColor-Eigenschaften gebunden.

Beachten Sie, dass DataTemplate den Typ NamedColor für das x:DataType-Attribut definiert, d.h., dass alle Bindungsausdrücke in der Ansichtshierarchie DataTemplate kompiliert werden. Dies können Sie überprüfen, indem Sie einen der Bindungsausdrücke so ändern, dass eine nicht vorhandene NamedColor-Eigenschaft gebunden wird, was zu einem Buildfehler führt. In diesem Beispiel wird das x:DataType-Attribut auf ein Zeichenfolgenliteral festgelegt. Sie können es jedoch auch auf einen Typ mit der Markuperweiterung x:Type festlegen. Weitere Informationen zur Markuperweiterung x:Type finden Sie unter x:Type-Markuperweiterung.

Wenn die Anwendung zum ersten Mal ausgeführt wird, wird die ListView-Klasse mit NamedColor-Instanzen aufgefüllt. Wenn ein Element in der ListView-Klasse ausgewählt wird, wird die Farbe des ausgewählten Elements für die BoxView.Color-Eigenschaft in der ListView-Klasse festgelegt:

Compiled Color List

Wenn andere Elemente in der ListView-Klasse ausgewählt werden, wird die Farbe der BoxView-Klasse aktualisiert.

Kombinieren von kompilierten und klassischen Bindungen

Bindungsausdrücke werden nur für die Ansichtshierarchie kompiliert, für die das Attribut x:DataType definiert ist. Im Gegensatz dazu, verwenden alle Ansichten in einer Hierarchie, für die das Attribut x:DataType nicht definiert ist, klassische Bindungen. Daher ist es möglich, kompilierte Bindungen und klassische Bindungen auf einer Seite zu kombinieren. Zum Beispiel verwenden die Ansichten in der DataTemplate-Klasse im vorherigen Abschnitt kompilierte Bindungen, während die BoxView-Klasse, die auf die in ListView ausgewählte Farbe festgelegt ist, klassische Bindungen verwendet.

Mithilfe sorgfältiger Strukturierung von x:DataType-Attributen kann deshalb eine Seite mit kompilierten und klassischen Bindungen erstellt werden. Alternativ kann das Attribut x:DataType jederzeit und an beliebiger Position in einer Ansichtshierarchie mithilfe der Markuperweiterung x:Null als null definiert werden. Dadurch wird impliziert, dass alle Bindungsausdrücke in der Ansichtshierarchie klassische Bindungen nutzen. Die Seite Mixed Bindings (Gemischte Bindungen) veranschaulicht diese Vorgehensweise:

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

Der StackLayout-Stamm legt den Typ HslColorViewModel für das Attribut x:DataType fest, d.h., dass alle Bindungsausdrücke im StackLayout-Stamm der Ansichtshierarchie kompiliert werden. Das Attribut x:DataType wird jedoch von der inneren StackLayout-Klasse mithilfe des Markupausdrucks x:Null mit dem Wert null neu definiert. Daher verwenden Bindungsausdrücke in der inneren StackLayout-Klasse klassische Bindungen. Nur die BoxView-Klasse im StackLayout-Stamm der Ansichtshierarchie verwendet kompilierte Bindungen.

Weitere Informationen über den Markupausdruck x:Null finden Sie unter x:Null Markup Extension (x:Null-Markuperweiterung).

Leistung

Kompilierte Bindungen verbessern die Leistung der Datenbindung mit variierenden Leistungsvorteilen. Unittests zeigen folgende Ergebnisse:

  • Eine kompilierte Bindung, die eine Eigenschaftsänderungsbenachrichtigung verwendet (z.B. eine OneWay-, OneWayToSource- oder TwoWay-Bindung), wird ungefähr achtmal so schnell wie eine klassische Bindung aufgelöst.
  • Eine kompilierte Bindung, die keine Eigenschaftsänderungsbenachrichtigung verwendet (z.B. eine OneTime-Bindung) wird ungefähr 20-mal so schnell wie eine klassische Bindung aufgelöst.
  • Das Festlegen der BindingContext-Eigenschaft für eine kompilierte Bindung, die eine Eigenschaftsänderungsbenachrichtigung verwendet (z.B. eine OneWay-, OneWayToSource- oder TwoWay-Bindung), wird ungefähr fünfmal so schnell wie eine auf BindingContext festgelegte klassische Bindung aufgelöst.
  • Das Festlegen der BindingContext-Eigenschaft für eine kompilierte Bindung, die keine Eigenschaftsänderungsbenachrichtigung verwendet (z.B. eine OneTime-Bindung), wird ungefähr siebenmal so schnell wie eine auf BindingContext festgelegte klassische Bindung aufgelöst.

Diese Leistungsunterschiede können bei mobilen Geräten abhängig von der verwendeten Plattform, der Version des verwendeten Betriebssystems und dem Gerät, auf dem die Anwendung ausgeführt wird, gesteigert werden.