Jämför ett händelsedrivet användargränssnitt med ett databundet användargränssnitt

Slutförd

Ett händelsedrivet användargränssnitt (UI) är utformat kring de händelser som en kontroll exponerar. Dessa händelser kan associeras med händelsehanterarkod som anropas när händelsen utlöses. Anta till exempel att du har en knapp som utför en tidskrävande åtgärd när du klickar på den. Händelsehanteraren som tilldelats Clicked händelsen kan starta åtgärden och sedan ange knappens IsEnabled egenskap till false, vilket förhindrar att knappen klickas igen medan åtgärden körs.

Ett databundet användargränssnitt använder databindning för att presentera och interagera med data. Egenskaper för kontroller är bundna till dataobjektets egenskaper och dessa bindningar kan identifiera ändringar i egenskaperna. I föregående exempel bör du överväga knappen som utför en tidskrävande åtgärd. I stället för att inaktivera knappen i code-behind IsEnabled är egenskapen bunden till dataobjektets IsBusy egenskap. När dataobjektet blir "upptaget" ändras knappens aktiverade tillstånd automatiskt så att det matchar.

Fördelar och nackdelar med att använda händelser och kod bakom

Att använda kontrollens händelsehanterare med kod bakom är ett snabbt och bekvämt sätt att utforma applogik för ditt användargränssnitt. Du använder kod för att anropa tjänster för att hämta data, utföra åtgärder på dessa data och interagera med kontrollerna på sidan. Koden används för att hålla användargränssnittet och data synkroniserade.

Överväg exemplet med en vädertjänstapp. Följande XAML-fragment innehåller en enkel användargränssnittsknapp som användaren väljer för att hämta de senaste data och uppdatera användargränssnittet med luftfuktigheten.

<VerticalStackLayout Margin="10">
    <HorizontalStackLayout Spacing="20">
        <Label Text="Postal Code:" VerticalOptions="Center" />
        <Entry x:Name="PostalCode" WidthRequest="100" />
        <Button x:Name="RefreshWeatherButton" Text="Refresh" WidthRequest="200" Clicked="RefreshWeatherButton_Clicked" />
    </HorizontalStackLayout>
    <Label x:Name="Humidity" Text="Humidity: ?" />
</VerticalStackLayout>

Skärmbild av en .NET MAUI-app som har en postkontroll för ett postnummer, en knapp med textuppdateringen. Under dessa två kontroller finns en etikett som representerar luftfuktigheten.

Det finns tre namngivna kontroller i det här exemplet:

  • Entry med namnet PostalCode.
  • Button kontroll med namnet RefreshWeatherButton.
  • Label kontroll med namnet Fuktighet.

RefreshWeatherButton Har en händelsehanterare deklarerad för Clicked händelsen. När knappen klickas frågar händelsehanteraren en vädertjänst efter den senaste väderprognosen med hjälp av de data som anges i PostalCode inmatningskontrollen och anger Humidity etikettens text till den aktuella luftfuktigheten.

private void RefreshWeatherButton_Clicked(object sender, EventArgs e)
{
    WeatherService.Location = PostalCode.Text;
    WeatherService.Refresh();
    Humidity.Text = $"Humidity: {WeatherService.Humidity}";
}

I den här händelsehanteraren är tre kontroller nära kopplade till varandra och data via koden bakom.

Den här designen fungerar bra för små UIs, men så snart användargränssnittet blir komplext kan det bli besvärligt att upprätthålla en nära kopplad kod bakom. Om du tar bort eller ändrar en kontroll måste du rensa all kod med hjälp av dessa användargränssnittskontroller, vilket kan inkludera händelsehanteraren. Om du bestämmer dig för att göra om användargränssnittet har du massor av kod att omstrukturera också. Och när den säkerhetskopierade datastrukturen ändras måste du gå in på koden för varje användargränssnitt för att hålla dig synkroniserad.

Databindning hjälper

Databindningar kan implementeras i XAML eller kod, men är mycket vanligare i XAML där de bidrar till att minska storleken på filen bakom koden. Genom att ersätta procedurkod i händelsehanterare med deklarativ kod eller pålägg förenklas och förtydligas appen. Eftersom bindningarna inte kräver kod bakom kan du enkelt skapa, ändra eller ändra användargränssnittet så att det passar hur du vill presentera data.

Låt oss ta samma exempel som i föregående avsnitt, men uppdatera det så att det använder databindning:

<VerticalStackLayout Margin="10">
    <HorizontalStackLayout Spacing="20">
        <Label Text="Postal Code:" VerticalOptions="Center" />
        <Entry Text="{Binding Location, Mode=OneWayToSource}" WidthRequest="100" />
        <Button Text="Refresh" Command="{Binding RefreshWeather}" WidthRequest="200" />
    </HorizontalStackLayout>
    <Label Text="{Binding Humidity}" />
</VerticalStackLayout>

Du kan upptäcka de egenskaper som är databundna. De använder XAML-tilläggssyntaxen {Binding ...} för egenskapens värde. Oroa dig inte för detaljerna ännu, som beskrivs senare i den här modulen.

Samma tre kontroller deklareras i XAML, men ingen av dem namnges eftersom ett namn inte krävs:

  • Entry kontroll:

    Den här kontrollens Text egenskap är bunden till en egenskap med namnet Location.

  • Button kontroll:

    Knappens Command egenskap är bunden till en egenskap med namnet RefreshWeather. Command är en egenskap på knappen som anropar kod när knappen trycks ned. Det är ett alternativ till händelsen Clicked som används i databindning.

  • Label kontroll:

    Den här Text egenskapen är bunden till en egenskap med namnet Humidity.

I det här enkla användargränssnittet elimineras all kod bakom. Att ta bort all bakomliggande kod är inte databindningens punkt, även om det vanligtvis är möjligt. Kod bakom har fortfarande sin plats. Hur mycket databindning du implementerar är upp till dig.

Nu är användargränssnittet löst kopplat till ett dataobjekt. Varför är den löst kopplad istället för tätt kopplad? På grund av hur bindningar utvärderas. Varje kontroll har en BindingContext egenskap. Om kontexten inte har angetts används den överordnade kontrollens kontext och så vidare tills XAML-roten utvärderas. När bindningar utvärderas kontrolleras kontextens objektinstans efter de egenskaper som krävs, till exempel etikettkontrollens Text bindning till kontextens Humidity egenskap. Om Humidity inte finns i kontexten händer ingenting.

Eftersom användargränssnittet är löst kopplat kan du göra om användargränssnittet utan att behöva brytkod. Du kan dock bryta funktioner. Du kan till exempel ta bort knappen och appen kompileras och körs fortfarande, men du kan inte uppdatera vädret. Å andra sidan kan du ersätta Entry kontrollerna och Button med den enda SearchBar kontrollen. Med den här kontrollen kan du ange text och anropa ett kommando.

<SearchBar Text="{Binding Location, Mode=OneWayToSource}" SearchCommand="{Binding RefreshWeather}" />

Som du ser kan databindning i användargränssnittsdesignen hjälpa dig att utveckla och ändra användargränssnittet utan mycket arbete. Användargränssnittet synkroniseras automatiskt med data och applogik separeras från användargränssnittet.

Kontrollera dina kunskaper

1.

Vilket av följande instruktioner beskriver hur databindningen förbättrar användargränssnittet?

2.

I en app som hämtar det senaste vädret är en etikettkontroll som representerar temperaturen bunden till dataobjektet. När användaren trycker på knappen "Hämta väder" och utlöser Clicked händelsen, vad skulle händelsehanterarkoden göra för att uppdatera användargränssnittet?