Xamarin.Forms Skompilowane powiązania

Skompilowane powiązania są rozwiązywane szybciej niż powiązania klasyczne, co zwiększa wydajność powiązań danych w Xamarin.Forms aplikacjach.

Powiązania danych mają dwa główne problemy:

  1. Nie ma walidacji wyrażeń powiązań w czasie kompilacji. Zamiast tego powiązania są rozwiązywane w czasie wykonywania. W związku z tym wszelkie nieprawidłowe powiązania nie są wykrywane, dopóki środowisko uruchomieniowe nie będzie działać zgodnie z oczekiwaniami lub pojawią się komunikaty o błędach.
  2. Nie są one opłacalne. Powiązania są rozwiązywane w czasie wykonywania przy użyciu inspekcji obiektów ogólnego przeznaczenia (odbicia), a obciążenie związane z wykonywaniem tej czynności różni się od platformy do platformy.

Skompilowane powiązania zwiększają wydajność powiązań danych w Xamarin.Forms aplikacjach przez rozpoznawanie wyrażeń powiązań w czasie kompilacji, a nie w czasie wykonywania. Ponadto ta walidacja czasu kompilacji wyrażeń powiązania umożliwia lepsze środowisko rozwiązywania problemów dla deweloperów, ponieważ nieprawidłowe powiązania są zgłaszane jako błędy kompilacji.

Proces używania skompilowanych powiązań polega na:

  1. Włącz kompilację XAML. Aby uzyskać więcej informacji na temat kompilacji XAML, zobacz Kompilacja XAML.
  2. x:DataType Ustaw atrybut na typ VisualElement obiektu, z którego VisualElement element i jego elementy podrzędne zostaną powiązane.

Uwaga

Zaleca się ustawienie atrybutu x:DataType na tym samym poziomie w hierarchii widoków BindingContext , co jest ustawione. Ten atrybut można jednak ponownie zdefiniować w dowolnej lokalizacji w hierarchii widoków.

Aby można było używać skompilowanych powiązań, x:DataType atrybut musi być ustawiony na literał ciągu lub typ przy użyciu x:Type rozszerzenia znaczników. W czasie kompilacji XAML wszelkie nieprawidłowe wyrażenia powiązania będą zgłaszane jako błędy kompilacji. Jednak kompilator XAML zgłosi tylko błąd kompilacji dla pierwszego nieprawidłowego wyrażenia powiązania, które napotka. Wszystkie prawidłowe wyrażenia powiązania zdefiniowane na VisualElement obiekcie lub jego elementach podrzędnych zostaną skompilowane, niezależnie od tego, czy BindingContext element jest ustawiony w języku XAML, czy kodzie. Kompilowanie wyrażenia powiązania generuje skompilowany kod, który pobierze wartość z właściwości w źródle i ustawi go we właściwości na obiekcie docelowym określonym w znaczniku. Ponadto w zależności od wyrażenia powiązania wygenerowany kod może obserwować zmiany w wartości właściwości źródłowej i odświeżyć właściwość docelową i może wypchnąć zmiany z obiektu docelowego z powrotem do źródła.

Ważne

Skompilowane powiązania są obecnie wyłączone dla wszystkich wyrażeń powiązań, które definiują Source właściwość. Jest to spowodowane tym, że Source właściwość jest zawsze ustawiana przy użyciu x:Reference rozszerzenia znaczników, którego nie można rozpoznać w czasie kompilacji.

Używanie skompilowanych powiązań

Na stronie Selektor kolorów skompilowanych pokazano, jak używać skompilowanych powiązań między widokami i właściwościami Xamarin.Forms modelu viewmodel:

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

Element główny StackLayout tworzy wystąpienie HslColorViewModel właściwości i inicjuje Color właściwość w tagach elementu właściwości dla BindingContext właściwości. Ten katalog główny StackLayout definiuje x:DataType również atrybut jako typ modelu widoku, co oznacza, że wszystkie wyrażenia powiązań w hierarchii widoku głównego StackLayout zostaną skompilowane. Można to zweryfikować, zmieniając dowolne wyrażenia powiązania, aby powiązać z nieistnieną właściwością viewmodel, co spowoduje błąd kompilacji. Chociaż w tym przykładzie x:DataType atrybut jest ustawiany na literał ciągu, można go również ustawić na typ z x:Type rozszerzeniem znaczników. Aby uzyskać więcej informacji na temat x:Type rozszerzenia znaczników, zobacz x:Type Markup Extension (Rozszerzenie znaczników x:Type).

Ważne

Atrybut x:DataType można ponownie zdefiniować w dowolnym momencie w hierarchii widoków.

BoxViewLabel Elementy i Slider widoki dziedziczą kontekst powiązania z elementu StackLayout. Te widoki to wszystkie obiekty docelowe powiązania odwołujące się do właściwości źródła w modelu widoku. BoxView.Color W przypadku właściwości i Label.Text właściwości powiązania danych to OneWay — właściwości w widoku są ustawione na podstawie właściwości w modelu widoków. Slider.Value Jednak właściwość używa TwoWay powiązania. Umożliwia to ustawienie każdego Slider z modelu widoków, a także ustawienie modelu widoku z każdego Sliderelementu .

Po pierwszym uruchomieniu aplikacji wszystkie BoxViewLabel elementy , i Slider elementy są ustawiane z modelu viewmodel na podstawie początkowej Color właściwości ustawionej podczas tworzenia wystąpienia modelu viewmodel. Przedstawiono to na poniższych zrzutach ekranu:

Selektor kolorów skompilowanych

Gdy suwaki są manipulowane, BoxView elementy i Label są odpowiednio aktualizowane.

Aby uzyskać więcej informacji na temat tego selektora kolorów, zobacz ViewModels (Modele widoków) i Property-Change Notifications (Powiadomienia dotyczące zmiany właściwości).

Używanie skompilowanych powiązań w elemecie DataTemplate

Powiązania w obiekcie DataTemplate są interpretowane w kontekście obiektu, który jest szablonowany. W związku z tym w przypadku używania skompilowanych powiązań w obiekcie DataTemplateDataTemplate należy zadeklarować typ obiektu danych przy użyciu atrybutu x:DataType .

Na stronie Skompilowana lista kolorów pokazano użycie skompilowanych powiązań w obiekcie DataTemplate:

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

Właściwość ListView.ItemsSource jest ustawiona na właściwość statyczną NamedColor.All . Klasa NamedColor używa odbicia platformy .NET do wyliczania wszystkich statycznych pól publicznych w Color strukturze i przechowywania ich nazw w kolekcji dostępnej z właściwości statycznej All . W związku z tym element ListView jest wypełniony wszystkimi NamedColor wystąpieniami. Dla każdego elementu w elemencie ListViewkontekst powiązania dla elementu jest ustawiony na NamedColor obiekt. BoxView Elementy i Label w obiekcie ViewCell są powiązane z NamedColor właściwościami.

Należy pamiętać, że DataTemplate atrybut definiuje jako x:DataType typ, wskazując, że wszystkie wyrażenia powiązania w DataTemplate hierarchii widoków zostaną skompilowane.NamedColor Można to zweryfikować, zmieniając dowolne wyrażenia powiązania, aby powiązać z nieistnieną NamedColor właściwością, co spowoduje błąd kompilacji. Chociaż w tym przykładzie x:DataType atrybut jest ustawiany na literał ciągu, można go również ustawić na typ z x:Type rozszerzeniem znaczników. Aby uzyskać więcej informacji na temat x:Type rozszerzenia znaczników, zobacz x:Type Markup Extension (Rozszerzenie znaczników x:Type).

Po pierwszym uruchomieniu ListView aplikacji element jest wypełniany wystąpieniami NamedColor . Po wybraniu BoxView.Color elementu w elemencie ListView właściwość jest ustawiana na kolor wybranego elementu w elemencie ListView:

Skompilowana lista kolorów

Wybranie innych elementów w pliku ListView aktualizuje kolor elementu BoxView.

Łączenie skompilowanych powiązań z powiązaniami klasycznymi

Wyrażenia powiązań są kompilowane tylko dla hierarchii widoków, na których x:DataType zdefiniowano atrybut. Z drugiej strony wszystkie widoki w hierarchii, w której x:DataType atrybut nie jest zdefiniowany, będą używać powiązań klasycznych. W związku z tym można połączyć skompilowane powiązania i powiązania klasyczne na stronie. Na przykład w poprzedniej sekcji widoki w ramach DataTemplate używanych skompilowanych powiązań, a BoxView kolor wybrany w elememencie ListView nie jest ustawiony.

Staranne struktury atrybutów x:DataType mogą zatem prowadzić do strony przy użyciu skompilowanych i klasycznych powiązań. Alternatywnie x:DataType atrybut można ponownie zdefiniować w dowolnym momencie w hierarchii widoków do null używania x:Null rozszerzenia znaczników. Oznacza to, że wszystkie wyrażenia powiązań w hierarchii widoków będą używać powiązań klasycznych. Na stronie Powiązania mieszane przedstawiono następujące podejście:

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

Katalog główny StackLayout ustawia atrybut HslColorViewModel jako x:DataType typ, wskazując, że każde wyrażenie powiązania w hierarchii widoku głównego StackLayout zostanie skompilowane. Jednak wewnętrzna StackLayout definicja atrybutu x:DataTypenull za pomocą x:Null wyrażenia znaczników. W związku z tym wyrażenia powiązania wewnętrzne StackLayout używają powiązań klasycznych. Tylko element BoxVieww hierarchii widoku głównego StackLayout używa skompilowanych powiązań.

Aby uzyskać więcej informacji o wyrażeniu x:Null znaczników, zobacz x:Null Markup Extension (Rozszerzenie znaczników o wartości null).

Wydajność

Skompilowane powiązania zwiększają wydajność powiązań danych, a korzyść z wydajności jest różna. Testy jednostkowe pokazują, że:

  • Skompilowane powiązanie korzystające z powiadomienia o zmianie właściwości (tj. OneWayOneWayToSource, lub TwoWay powiązania) jest rozpoznawane mniej więcej 8 razy szybciej niż powiązanie klasyczne.
  • Skompilowane powiązanie, które nie używa powiadomienia o zmianie właściwości (tj. OneTime powiązanie) jest rozpoznawane mniej więcej 20 razy szybciej niż powiązanie klasyczne.
  • BindingContext Ustawienie elementu na skompilowanym powiązaniu używającym powiadomienia o zmianie właściwości (tj. OneWayOneWayToSource, lub TwoWay powiązania) jest o około 5 razy szybsze niż ustawienie BindingContext dla powiązania klasycznego.
  • BindingContext Ustawienie elementu na skompilowanym powiązaniu, które nie używa powiadomienia o zmianie właściwości (tj. OneTime powiązanie) jest mniej więcej 7 razy szybsze niż ustawienie BindingContext elementu w powiązaniu klasycznym.

Te różnice wydajności można powiększyć na urządzeniach przenośnych, zależnie od używanej platformy, wersji używanego systemu operacyjnego i urządzenia, na którym działa aplikacja.