Använda databindningar i XAML

Slutförd

Databindningar kan deklareras i antingen kod eller I XAML med hjälp av markeringstillägg. I den här lektionen beskrivs det senare eftersom det är det vanligaste sättet att skapa bindningar. Det finns ett par skäl att föredra XAML. För det första anser de flesta att bindningar är en del av användargränssnittskoden eftersom bindningarna hämtar data som användargränssnittet ska visa. För det andra finns det ett tillägg med namnet Binding som gör det enkelt att göra det.

Vad är databindningar?

En bindning kopplar ihop två egenskaper. En egenskap finns i användargränssnittet och den andra finns i datamodellobjektet. Om värdet för någon av egenskaperna ändras kan bindningsobjektet uppdatera det andra. Med andra ord är bindningar mellanliggande objekt som synkroniserar användargränssnittet och data. Vi använder termerna källa och mål för att identifiera de två objekt som ingår:

  • Källa: En källa kan vara ett objekt av vilken typ som helst. I praktiken använder du vanligtvis ett dataobjekt som källa. Du måste identifiera egenskapen för källobjektet för att delta i bindningen. Du identifierar egenskapen genom att Path ange egenskapen i bindningen.

  • Mål: Målet är en egenskap som implementeras med hjälp av en särskild egenskap som kallas för .BindableProperty Objektet med BindableProperty måste härledas från BindableObject. Alla kontroller som tillhandahålls i .NET MAUI härleds från BindableObject och de flesta av deras egenskaper är BindableProperties.

Följande diagram visar hur en bindning är ett mellanliggande objekt mellan två egenskaper:

Ett diagram som illustrerar en bindning som mellanhand mellan en källobjektegenskap och en bindbar målobjektegenskap.

Så här skapar du en databindning i XAML

Nu ska vi titta på en enkel bindning som skapats i XAML med hjälp av markeringstillägget {Binding} . Den binder WeatherService.Humidity källans egenskap till Text egenskapen för användargränssnittskontrollen.

<VerticalStackLayout Margin="10">
    <VerticalStackLayout.Resources>
        <ResourceDictionary>
            <services:WeatherService x:Key="myWeatherService" />
        </ResourceDictionary>
    </VerticalStackLayout.Resources>

    <Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" />
</VerticalStackLayout>

Bindningskällan är:

  • En objektinstans av WeatherService typen. Instansen {StaticResource ...} refereras via XAML-tillägget, som pekar på ett objekt i stacklayoutens resursordlista.

  • Pekar Path på en egenskap med namnet HumidityWeatherService typen.

    Path är den första namnlösa parametern i syntaxen {Binding} och syntaxen Path= kan utelämnas. Dessa två bindningar är likvärdiga:

    <Label Text="{Binding Path=Humidity, Source={StaticResource myWeatherService}}" />
    <Label Text="{Binding Humidity, Source={StaticResource myWeatherService}}" />
    

Bindningsmålet är:

  • Kontrollen Label .
  • Kontrollens Text egenskap.

När användargränssnittet visas {Binding} skapar XAML-tillägget en bindning mellan WeatherService och Label. Bindningen läser in WeatherService.Humidity egenskapens värde i egenskapen Label.Text .

Använda en annan kontroll som bindningskälla

En användbar funktion i bindningen är att kunna binda till andra kontroller. Följande XAML är en enkel demonstration:

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

Egenskapen Slider.Value är bunden till Label.Rotation egenskapen, men på ett annat sätt än tidigare förklarat. Den här egenskapen använder bindningsläget OneWayToSource, som vänder den typiska bindningsmekanismen. I stället för att källan uppdaterar måletOneWayToSource uppdaterar källan när målet ändras. I det här exemplet när skjutreglaget flyttas uppdateras rotationen av etiketten baserat på skjutreglagets värde, enligt följande animering:

En animerad bild av en skjutreglagekontroll som dras med en mus. När skjutreglaget flyttas roteras en textbit för att matcha skjutreglagets position.

Det vanliga scenariot för bindning av kontroller till varandra är när en kontroll, vanligtvis en samlingskontroll som en ListView eller CarouselView, har ett markerat objekt som du vill använda som datakälla. I exemplet med en sida som visar väderprognosen kan du ha en ListView aktuell femdagarsprognos. När användaren väljer en dag i listan visas informationen om väderprognosen i andra kontroller. Om användaren väljer en annan dag uppdateras de andra kontrollerna igen med den valda dagens information.

Använd samma källa för flera bindningar

I föregående exempel visades användning av en statisk resurs som källa för en enda bindning. Den källan kan användas i flera bindningar. Här är ett exempel på hur du deklarerar en bindning mellan tre olika kontroller, alla bindningar till samma objekt och egenskap Path, även om vissa utelämnar Path egenskapen:

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

Du behöver inte använda samma Path när du använder samma 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>

Sällan presenterar du en enda datamängd från en källa, även om det kan hända. Vanligtvis har du flera kontroller som använder olika datadelar från samma källa. Den här situationen är så vanlig att BindableObject klassen har en egenskap med namnet BindingContext som fungerar som källa för databindning. Kom ihåg att .NET MAUI-kontroller ärver från BindableObject klassen, så .NET MAUI-kontrollerna har BindingContext egenskapen .

Source Det är valfritt att ange bindningen. En bindning som inte har Source angetts söker automatiskt i det visuella XAML-trädet efter en BindingContext, som anges i XAML eller tilldelas till ett överordnat element efter kod. Bindningar utvärderas enligt det här mönstret:

  1. Om bindningen definierar en Sourceanvänds den källan och sökningen stoppas. Bindningarna Path tillämpas på Source för att hämta ett värde. Om Source inte har angetts börjar sökningen efter en bindningskälla.

  2. Sökningen börjar med själva målobjektet. Om målobjektets inte är null stoppas BindingContext sökningen och bindningarna Path tillämpas på för att BindingContext hämta ett värde. Om är BindingContext null fortsätter sökningen.

  3. Den här processen fortsätter tills den når XAML-roten. Sökningen avslutas genom att kontrollera BindingContext rotens värde för ett värde som inte är null. Om inget giltigt BindingContext hittades har bindningen inget att binda mot och gör ingenting.

Det är vanligt att ange BindingContext på rotobjektets nivå för att tillämpa på hela XAML.

Det finns en sista praktisk funktion som är värd att nämna. Bindningar söker efter ändringar i objektreferensen för källan. Detta fungerar även för bindningar som använder BindingContext som källa. Source Om eller BindingContext omtilldelas till ett annat objekt hämtar bindningarna data från den nya källan och uppdaterar målet.

Kontrollera dina kunskaper

1.

Vilket gäller för källobjektet i en .NET MAUI-bindning?

2.

Vilket gäller för målegenskapen i .NET MAUI-bindningen?

3.

Om alla bindningar för kontroller inom ett Grid behöver samma källobjekt, vilken är den säkraste strategin att bara ange källobjektet en gång?