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:
- 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.
- 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:
- Włącz kompilację XAML. Aby uzyskać więcej informacji na temat kompilacji XAML, zobacz Kompilacja XAML.
x:DataType
Ustaw atrybut na typVisualElement
obiektu, z któregoVisualElement
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.
BoxView
Label
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 Slider
elementu .
Po pierwszym uruchomieniu aplikacji wszystkie BoxView
Label
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:
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 DataTemplate
DataTemplate
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 ListView
kontekst 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
:
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:DataType
null
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 BoxView
w 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.
OneWay
OneWayToSource
, lubTwoWay
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.OneWay
OneWayToSource
, lubTwoWay
powiązania) jest o około 5 razy szybsze niż ustawienieBindingContext
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ż ustawienieBindingContext
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.