Skapa ett konsekvent användargränssnitt med hjälp av formatmallar

Slutförd

I .NET Multi-Platform App UI (MAUI) är resurserna bra för att undvika hårdkodade, duplicerade värden i XAML-pålägget (Extensible Application Markup Language), men de kan vara omständliga att tillämpa. Du tilldelar varje egenskapsvärde individuellt, vilket kan resultera i rörig och utförlig XAML. Den här lektionen visar hur du grupperar flera inställningar i ett format, vilket kan hjälpa dig att rensa koden och göra den mer underhållsbar.

Så här kan resurser belamra din XAML

En resurs ger ett värde för en enskild egenskap. Att använda många resurser kan dock leda till utförlig XAML. Anta att du vill ha ett anpassat utseende för dina knappar. Först skapar du resurser för de värden som du behöver. Sedan tillämpar du varje resurs på alla knappar. Följande kod visar hur XAML-pålägget kan leta efter två knappar.

<Button
    Text = "OK"
    BackgroundColor = "{StaticResource highlightColor}"
    BorderColor = "{StaticResource borderColor}"
    BorderWidth = "{StaticResource borderWidth}"
    TextColor = "{StaticResource textColor}" />

<Button
    Text = "Cancel"
    BackgroundColor = "{StaticResource highlightColor}"
    BorderColor = "{StaticResource borderColor}"
    BorderWidth = "{StaticResource borderWidth}"
    TextColor = "{StaticResource textColor}" />

Observera hur samma fem egenskaper anges på var och en av knapparna. Om du använder resurser tar du bort behovet av upprepade hårdkodade värden i fyra av dem. Den här typen av XAML-pålägg blir dock snabbt svårläst. Om du ställer in ett stort antal egenskaper för varje kontroll är det dessutom enkelt att oavsiktligt utelämna en av dem, vilket leder till inkonsekvenser i kontrollernas utseende. Lösningen är att skapa ett format som tilldelar alla fyra egenskaperna samtidigt.

Vad är en setter?

Setters är de viktigaste komponenterna som du använder för att skapa formatmallar.

En setter är en container för ett egenskaps-/värdepar. Du kan tänka dig att en setter representerar en tilldelningsinstruklikering. Du anger vilken egenskap som ska tilldelas och vilket värde som ska tillämpas. Vanligtvis skapar du Setter-objekt i XAML-pålägget. I följande exempel skapas ett Setter-objekt för egenskapen TextColor .

<Setter Property="TextColor" Value="White" />

Du kan använda en resurs för värdet i en setter, enligt följande kod. Den här tekniken är bra när du vill använda samma värde i flera setters.

<Setter Property="TextColor" Value="{StaticResource textColor}" />

Kommentar

Det egenskapsvärde som du anger i en setter måste implementeras som en bindbar egenskap. Alla egenskaper för kontroller i .NET MAUI som slutar med suffixegenskapen är bindbara egenskaper. Om du försöker använda en egenskap som TextColor i en setter kontrollerar du att det finns en motsvarande bindbar egenskap med namnet TextColorProperty för den kontrollen. I praktiken implementeras nästan alla egenskaper som du vill använda i dina setters på det här sättet.

Vad är ett format?

Ett format är en samling set som är inriktade på en viss typ av kontroll. .NET MAUI kräver en måltyp så att den kan se till att egenskaperna i dina setters finns på den typen.

Följande kod visar ett format som kombinerar de fyra värdena från föregående exempel. Observera att TargetType är inställt på Knapp och att alla egenskaper i setters är medlemmar i klassen Button . Du kan inte använda det här formatet för en etikett eftersom klassen Etikett inte innehåller egenskapen BorderColor eller BorderWidth .

<Style TargetType="Button">
    <Setter Property="BackgroundColor" Value="#2A84D3" />
    <Setter Property="BorderColor" Value="#1C5F9B" />
    <Setter Property="BorderWidth" Value="3" />
    <Setter Property="TextColor" Value="White" />
</Style>

Definiera ett format

Du definierar vanligtvis formatmallar som resurser i ett ResourceDictionary-objekt . En resursordlista gör det enkelt att använda formatet över flera kontroller på samma sida, eller till och med i hela programmet. Följande kod visar hur du definierar ett format som en resurs i en ordlista. Observera att formatet får ett namn med hjälp av egenskapen x:Key . Om du namnger ett format kan du referera till det från dina XAML-sidor.

<ContentPage.Resources>
    <Style x:Key="MyButtonStyle" TargetType="Button">
        ...
    </Style>
</ContentPage.Resources>

Använda ett format

Du kopplar ett format till en kontroll genom att tilldela namnet till egenskapen Style . Tilldelningen gör att vart och ett av Setter-objekten i formatet tillämpas på målkontrollen. Följande kod visar hur du använder ett knappformat på två knappar.

<Button Text="OK" Style="{StaticResource MyButtonStyle}" />
<Button Text="Cancel" Style="{StaticResource MyButtonStyle}" />

I föregående exempel använde du tillägget StaticResource-markering för att koppla formatmallen till kontrollerna. Den här tekniken är bra när du inte behöver formatet för att ändra vid körning. Men vad händer om du vill implementera något som dynamiska teman, där användargränssnittet behöver ändras? I det här fallet kan du använda markeringstillägget DynamicResource för att läsa in formatet.

<Button Text="Cancel" Style="{DynamicResource MyButtonStyle}" />

DynamicResource lyssnar efter ersättning av egenskapen x:Key i resursordlistan. Om du skriver kod som läser in ett nytt format i ResourceDictionary med samma x:Key-värde tillämpas det nya formatet automatiskt på användargränssnittet.

Använda ett implicit format för flera kontroller

Anta att användargränssnittet har 50 knappar och att du vill använda samma formatmall för alla. Med det vi vet hittills behöver du tilldela egenskapen Format på varje knapp manuellt. Det är inte så svårt att göra, men det är fortfarande tråkigt.

Ett implicit format är ett format som du lägger till i en resursordlista utan att ge den en x:Key-identifierare . Implicita format tillämpas automatiskt på alla kontroller i det angivna TargetType-objektet .

Följande kod visar föregående exempel som deklarerats som ett implicit format. Det här formatet tillämpas på varje knapp på sidan.

<ContentPage.Resources>
    <Style TargetType="Button">
        <Setter Property="BackgroundColor" Value="Blue" />
        <Setter Property="BorderColor" Value="Navy" />
        ...
    </Style>
</ContentPage.Resources>

Viktigt!

Matchningen av implicita format till kontroller kräver en exakt matchning till den angivna TargetType. Kontroller som ärver från måltypen tar inte emot formatmallarna. Om du vill påverka ärvda kontroller kan du ange attributet Style.ApplyToDerivedTypes till True när du definierar formatet. Om du till exempel vill använda ett format på knapptypen och låta det påverka någon av dina knappar som ärver från Button (till exempel en ImageButton, RadioButton eller en anpassad typ som du skapar) kan du använda ett format som det här.

<ContentPage.Resources>
    <Style TargetType="Button"
           ApplyToDerivedTypes="True">
        <Setter Property="BackgroundColor" Value="Black" />
    </Style>
</ContentPage.Resources>

Åsidosätt ett format

Du kan tänka dig ett format som tillhandahåller en uppsättning standardvärden för kontroller. Ett befintligt format kan vara nära dina krav, men innehåller en eller två setters som du inte vill använda. I så fall kan du använda formatet och sedan åsidosätta värdet genom att ange egenskaper direkt. Den explicita inställningen tillämpas efter formatet, så det åsidosätter värdet från formatet.

Anta att du vill använda följande formatmall för flera knappar på sidan.

<Style x:Key="MyButtonStyle" TargetType="Button">
    <Setter Property="BackgroundColor" Value="Blue" />
    <Setter Property="BorderRadius" Value="10" />
    <Setter Property="BorderWidth" Value="3" />
</Style>

Det här formatet fungerar för alla knappar utom Avbryt, som behöver en röd bakgrund. Du kan använda samma formatmall för knappen Avbryt så länge du även ställer in egenskapen BackgroundColor direkt. Följande kod visar hur du åsidosätter färginställningen.

<Button
    Text="Cancel"
    Style="{StaticResource MyButtonStyle}"
    BackgroundColor="Red"
    ... />

Rikta in sig på en överordnad typ

Anta att du vill ha en anpassad bakgrundsfärg för dina knappar och etiketter. Du kan skapa separata formatmallar för varje typ, eller så kan du skapa ett format med TargetType inställt på VisualElement. Den här tekniken fungerar eftersom VisualElement är en basklass för både Knapp och Etikett.

Följande kod visar ett format som är avsett för en basklass som tillämpas på två olika härledda typer.

<Style x:Key="MyVisualElementStyle" TargetType="VisualElement">
    <Setter Property="BackgroundColor" Value="#2A84D3" />
</Style>
...
<Button Style="{StaticResource MyVisualElementStyle}" ... />
<Label Style="{StaticResource MyVisualElementStyle}" ... />

Det här exemplet identifierar formatmallen med hjälp av x:Key och kontrollerna tillämpar det explicit. Ett implicit format fungerar inte här eftersom TargetType för ett implicit format måste vara en exakt matchning till kontrolltypen.

Använda BasedOn för att ärva från ett format

Anta att du vill skapa ett sammanhängande utseende för användargränssnittet. Du bestämmer dig för att alla kontroller ska använda en konsekvent bakgrundsfärg. Bakgrundsfärginställningen visas troligen i fler än en av dina formatmallar. Följande kod visar två formatmallar med en upprepad setter.

<Style x:Key="MyButtonStyle" TargetType="Button">
    <Setter Property="BackgroundColor" Value="Blue" />
    <Setter Property="BorderColor" Value="Navy" />
    <Setter Property="BorderWidth" Value="5" />
</Style>

<Style x:Key="MyEntryStyle" TargetType="Entry">
    <Setter Property="BackgroundColor" Value="Blue" />
    <Setter Property="TextColor" Value="White" />
</Style>

Du kan använda formatarv för att räkna ut duplicerade setter till ett basformat. Om du vill skapa ett härlett format anger du dess BasedOn-egenskap så att den refererar till basformatet. Det nya formatet ärver alla setters från dess basformat. Det härledda formatet kan också lägga till nya setters eller ersätta en ärvd setter med en som innehåller ett annat värde.

Följande kod visar formatmallarna från föregående exempel som omstrukturerats till en hierarki. Den gemensamma settern visas bara i basformatet i stället för att upprepas. Observera att du använder Tillägget StaticResource-markering för att leta upp basformatet. Du kan inte använda DynamicResource i den här situationen.

<Style x:Key="MyVisualElementStyle" TargetType="VisualElement">
    <Setter Property="BackgroundColor" Value="Blue" />
</Style>

<Style x:Key="MyButtonStyle" TargetType="Button" BasedOn="{StaticResource MyVisualElementStyle}">
    <Setter Property="BorderColor" Value="Navy" />
    <Setter Property="BorderWidth" Value="5" />
</Style>

<Style x:Key="MyEntryStyle" TargetType="Entry" BasedOn="{StaticResource MyVisualElementStyle}">
    <Setter Property="TextColor" Value="White" />
</Style>

TargetType-värdet för bas- och härledda formatmallar måste vara kompatibelt. För att formaten ska vara kompatibla måste de antingen ha samma TargetType-egenskap , eller så är TargetType för det härledda formatet en underordnade till TargetType för basformatet.

Kunskapstest

1.

Varför skulle du definiera ett format i en ResourceDictionary?