Mobiele apps programmeren met Xamarin – XAML optimalisatie volgens het DRY-principe – XAML Resources

print

Inhoud


Wat vooraf ging


Resources


Resources bieden de mogelijkheid om properties van objecten geen specifieke waarde te geven maar via een referentie te laten verwijzen naar een bron. Deze verwijzing kan op verschillende plaatsen binnen de XAML herhaald worden en vervangen zo de herhaling van specifieke code (en komen bijgevolg tegemoet aan het Dry-principe.

  • Start een nieuw Xamarin-project en geef het een passende naam.
  • Voeg onderstaande onderstaande XAML toe aan de MainPage.xaml.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:XAMLExtensies" x:Class="XAMLExtensies.MainPage">

    <StackLayout>
        <Button Text="Do this!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" BorderWidth="3" Rotation="-15" TextColor="Red" Font="Large" />
        <Button Text="Do that!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" BorderWidth="3" Rotation="-15" TextColor="Red" Font="Large" />
        <Button Text="Do the other thing!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" BorderWidth="3" Rotation="-15" TextColor="Red" Font="Large" />
    </StackLayout>

</ContentPage>

Merk op dat heel veel eigenschappen/properties dezelfde waarden hebben. We zouden deze weerkerende waarden kunnen verzamelen, een naam geven en dan via deze naam aanroepen.

Deze waarden worden verzameld in een ResourceDictionary. Deze ResourceDictionary kunnen zich op verschillende niveaus bevinden. Bijvoorbeeld op het niveau van de applicatie of op het niveau van de pagina.

  • Open App.xaml.

Merk op dat er reeds ruimte voorzien is voor de ResourceDictionary.

<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="XAMLExtensies.App">
	<Application.Resources>

		<!-- Application resource dictionary -->

	</Application.Resources>
</Application>

Wij voegen onze ResourceDictionary toe aan de ContentPage. Weet dat u deze ResourceDictionary ook op een andere niveau, bv. het niveau van de StackLayout had kunnen toevoegen. Een ResourceDictionary toegevoegd op het niveau van de ContentPage is in heel deze pagina toegankelijk. Een ResourceDictionary toegevoegd op een lager niveau, bv. binnen een StackLayout, is alleen binnen dit lagere, binnen de specifieke StackLayout, toegankelijk.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:XAMLExtensies" x:Class="XAMLExtensies.MainPage">

    <ContentPage.Resources>
        <ResourceDictionary>

        </ResourceDictionary>
    </ContentPage.Resources>

    <StackLayout>
        <Button Text="Do this!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" BorderWidth="3" Rotation="-15" TextColor="Red" Font="Large" />
        <Button Text="Do that!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" BorderWidth="3" Rotation="-15" TextColor="Red" Font="Large" />
        <Button Text="Do the other thing!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" BorderWidth="3" Rotation="-15" TextColor="Red" Font="Large" />
    </StackLayout>

</ContentPage>

Nu we de ruimte afgebakend hebben waar de bronnen/Resources kunnen komen gaan we deze bronnen toekennen.

Iedere Resource is:

  • van een specifiek type
  • heeft een naam x:Key
  • heeft een waarde, van het specifieke type, eventueel toegekend aan een specifieke eigenschap.

Elke Button heeft een eigenschap HorizontalOptions="Center". Deze eigenschap is van het type LayoutOptions. De Resource kan als volgt worden aangeduid:

<LayoutOptions x:Key="horzOptions" Alignment="Center" />

Deze Resource is:

  • van het specifiek type: LayoutOptions
  • heeft de naam x:Key="horzOptions"
  • kent de waarde aan de eigenschap Alignment="Center" toe

Analoog kan de Resource aangemaakt worden voor VerticalOptions="CenterAndExpand". Merk op dat hier 2 eigenschappen een waarde krijgen.

<LayoutOptions x:Key="vertOptions" Alignment="Center" Expands="True" />

Elke Button heeft een eigenschap BorderWidth="3". Deze eigenschap is van het type Double. Er wordt geen eigenschap ingesteld maar enkel een waarde toegekend.

<x:Double x:Key="borderWidth">3</x:Double>

Analoog kunnen we ook de andere Resource instellen.

<x:Double x:Key="rotationAngle">-15</x:Double>
<Font x:Key="font">Large</Font>

De eigenschap kan platform specifiek ingesteld worden.

<OnPlatform x:Key="textColor" x:TypeArguments="Color" iOS="Red" Android="Aqua" WinPhone="#80FF80" />

De complete code is nu:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:XAMLExtensies" x:Class="XAMLExtensies.MainPage">

    <ContentPage.Resources>
        <ResourceDictionary>
             <LayoutOptions x:Key="horzOptions" Alignment="Center" />
             <LayoutOptions x:Key="vertOptions" Alignment="Center" Expands="True" />
             <x:Double x:Key="borderWidth">3</x:Double>
             <x:Double x:Key="rotationAngle">-15</x:Double>
             <OnPlatform x:Key="textColor" x:TypeArguments="Color" iOS="Red" Android="Aqua" WinPhone="#80FF80" />
             <Font x:Key="font">Large</Font>
        </ResourceDictionary>
    </ContentPage.Resources>

    <StackLayout>
        <Button Text="Do this!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" BorderWidth="3" Rotation="-15" TextColor="Red" Font="Large" />
        <Button Text="Do that!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" BorderWidth="3" Rotation="-15" TextColor="Red" Font="Large" />
        <Button Text="Do the other thing!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" BorderWidth="3" Rotation="-15" TextColor="Red" Font="Large" />
    </StackLayout>

</ContentPage>

We hebben nu wel de Resources bepaald maar nog niet gebruikt.

Verwijzingen naar Resources komen tussen {} en bevatten een:

  • Gebruik DynamicResource om te verwijzen naar een Resource indien de waarde dynamisch is en dus kan wijzigen in de loop van het programma.
  • StaticResource om te verwijzen naar een Resource indien de waarde statisch is en dus niet kan wijzigen .

Vervolgens volgt de naam van de Resource.

HorizontalOptions="{StaticResource horzOptions}"
VerticalOptions="{StaticResource vertOptions}"

De volledige XAML wordt nu:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:XAMLExtensies" x:Class="XAMLExtensies.MainPage">

    <ContentPage.Resources>
        <ResourceDictionary>
             <LayoutOptions x:Key="horzOptions" Alignment="Center" />
             <LayoutOptions x:Key="vertOptions" Alignment="Center" Expands="True" />
             <x:Double x:Key="borderWidth">3</x:Double>
             <x:Double x:Key="rotationAngle">-15</x:Double>
             <OnPlatform x:Key="textColor" x:TypeArguments="Color" iOS="Red" Android="Aqua" WinPhone="#80FF80" />
             <Font x:Key="font">Large</Font>
        </ResourceDictionary>
    </ContentPage.Resources>

    <StackLayout>
        <Button Text="Do this!" HorizontalOptions="{StaticResource horzOptions}" VerticalOptions="{StaticResource vertOptions}" BorderWidth="{StaticResource borderWidth}" Rotation="{StaticResource rotationAngle}" TextColor="{StaticResource textColor}" Font="{StaticResource font}" />
        <Button Text="Do that!" HorizontalOptions="{StaticResource horzOptions}" VerticalOptions="{StaticResource vertOptions}" BorderWidth="{StaticResource borderWidth}" Rotation="{StaticResource rotationAngle}" TextColor="{StaticResource textColor}" Font="{StaticResource font}" />
        <Button Text="Do the other thing!" HorizontalOptions="{StaticResource horzOptions}" VerticalOptions="{StaticResource vertOptions}" BorderWidth="{StaticResource borderWidth}" Rotation="{StaticResource rotationAngle}" TextColor="{StaticResource textColor}" Font="{StaticResource font}" />
    </StackLayout>

</ContentPage>

U zou kunnen argumenteren dat de code er niet bepaald korter op geworden is. En dit klopt, alleen is ze nu veel gemakkelijker te onderhouden. Stel dat u een rotatie wilt van 30 dan moet u dit maar op één plek meer wijzigen.


x:Static

x:Static wordt gebruikt om te verwijzen naar publieke statische velden, eigenschappen,… gedefinieerd in C#.

Deze publieke statische velden, eigenschappen,… worden gedeclareerd in een C#-klasse.

We gaan dit bespreken via een voorbeeld.

  • Start een nieuw Xamarin-project en geef het een passende naam (of werk verder in het bovenstaande project).

De constanten (public static readonly) aanmaken in C# klasse

  • Voeg een Class toe aan het project (rechts klikken op het project (portable app) – Add – New item…).

  • Selecteer Visual C# – Class en geef het een passende naam (bv. AppConstants).

  • Onderstaande klasse wordt aangemaakt.
namespace XAMLExtensies
{
    class AppConstants
    {
    }
}

We gaan aan deze klasse de nodige constanten toevoegen. Dit gebeurt via public static readonly gevolgd door het type en de naam.

Bijvoorbeeld een constante om de Padding bij te houden.

public static readonly Thickness PagePadding = new Thickness(5, Device.OnPlatform(20, 0, 0), 5, 0);
  • Maak onderstaande constanten.
using Xamarin.Forms;

namespace XAMLExtensies
{

    static class AppConstants
    {
        public static readonly Thickness PagePadding = new Thickness(5, Device.OnPlatform(20, 0, 0), 5, 0);
        public static readonly Font TitleFont = Font.SystemFontOfSize(Device.OnPlatform(35, 40, 50), FontAttributes.Bold);
        public static readonly Color BackgroundColor = Device.OnPlatform(Color.White, Color.Black, Color.Black);
        public static readonly Color ForegroundColor = Device.OnPlatform(Color.Black, Color.White, Color.White);
    }
}

Constanten oproepen in XAML

Het aanspreken van deze constanten gebeurt in 2 stappen.

  1. Neem de Namespace op in de XAML.
  2. Verwijs naar de specifieke constante met x:Static.

De Namespace opnemen

Een nieuwe XAML-pagina bevat reeds de opname van 2 standaard Namespace aangeduid met xmlns, eventueel gevolgd door een naam xmlns:x.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="XAMLExtensies.XAMLStatic">
</ContentPage>

We voegen hier nu een verwijzing naar onze eigen lokale Namespace toe.

xmlns:local="clr-namespace:XAMLExtensies"

Hierbij is local een zelfgekozen naam en XAMLExtensies de naam van ons project.

De volledige XAML is nu:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:XAMLExtensies" x:Class="XAMLExtensies.XAMLStatic">
</ContentPage>

Verwijs naar de specifieke constante met x:Static

Nu we de Namespace kunnen we via de gekozen naam verwijzen naar constanten in deze Namespace. We doen dit tussen {}, met x:Static en vervolgens een verwijzing naar de namespace.class.constante.

Padding="{x:Static local:AppConstants.PagePadding}"

Onderstaand eenvoudige voorbeeld toont hoe u dit kunt in de praktijk brengen.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:XAMLExtensies" x:Class="XAMLExtensies.XAMLStatic" Padding="{x:Static local:AppConstants.PagePadding}">

    <StackLayout>
        <Label Text="PCVO Dender en Schelde!" TextColor="{x:Static local:AppConstants.ForegroundColor}" BackgroundColor="{x:Static local:AppConstants.BackgroundColor}" Font="{x:Static local:AppConstants.TitleFont}" HorizontalOptions="Center" />
    </StackLayout>
</ContentPage>

Wie meer wil weten over hoe dit achterliggend nu precies allemaal werkt kan onderstaande video bekijken.


Behandelde Basiscompetenties uit de module ICT Programmeren – Specifieke ontwikkelomgeving: complexe functionaliteiten

  • IC BC253 – kan broncode in een specifieke ontwikkelomgeving optimaliseren

Geef een reactie

  • Abonneer je op deze website d.m.v. e-mail

    Voer je e-mailadres in om je in te schrijven op deze website en e-mailmeldingen te ontvangen van nieuwe berichten.