Freigeben über


Teil 2: Grundlegende XAML-Syntax

XAML ist hauptsächlich für die Instanziierung und Initialisierung von Objekten gedacht. Oft müssen jedoch Eigenschaften für komplexe Objekte festgelegt werden, die sich nicht einfach als XML-Strings darstellen lassen, und manchmal müssen Eigenschaften, die von einer Klasse definiert wurden, für eine untergeordnete Klasse festgelegt werden. Diese beiden Anforderungen erfordern die grundlegenden XAML-Syntaxmerkmale von Eigenschaftselementen und angehängten Eigenschaften.

Eigenschaftselemente

In XAML werden Eigenschaften von Klassen normalerweise als XML-Attribute festgelegt:

<Label Text="Hello, XAML!"
       VerticalOptions="Center"
       FontAttributes="Bold"
       FontSize="Large"
       TextColor="Aqua" />

Es gibt jedoch eine alternative Möglichkeit zum Festlegen einer Eigenschaft in XAML. Um diese Alternative zu TextColorversuchen, löschen Sie zuerst die vorhandene TextColor Einstellung:

<Label Text="Hello, XAML!"
       VerticalOptions="Center"
       FontAttributes="Bold"
       FontSize="Large" />

Öffnen Sie das Leere-Element-Tag Label , indem Sie es in Start- und Endtags trennen:

<Label Text="Hello, XAML!"
       VerticalOptions="Center"
       FontAttributes="Bold"
       FontSize="Large">

</Label>

Fügen Sie in diesen Tags Start- und Endtags hinzu, die aus dem Klassennamen und einem Eigenschaftsnamen bestehen, der durch einen Punkt getrennt ist:

<Label Text="Hello, XAML!"
       VerticalOptions="Center"
       FontAttributes="Bold"
       FontSize="Large">
    <Label.TextColor>

    </Label.TextColor>
</Label>

Legen Sie den Eigenschaftswert wie folgt als Inhalt dieser neuen Tags fest:

<Label Text="Hello, XAML!"
       VerticalOptions="Center"
       FontAttributes="Bold"
       FontSize="Large">
    <Label.TextColor>
        Aqua
    </Label.TextColor>
</Label>

Diese beiden Methoden zum Angeben der TextColor Eigenschaft sind funktional gleichwertig, verwenden aber nicht die beiden Methoden für dieselbe Eigenschaft, da dies effektiv das Festlegen der Eigenschaft zweimal sein würde und möglicherweise mehrdeutig sein könnte.

Mit dieser neuen Syntax können einige praktische Terminologie eingeführt werden:

  • Label ist ein Objektelement. Es handelt sich um ein Xamarin.Forms Objekt, das als XML-Element ausgedrückt wird.
  • Text, VerticalOptions, FontAttributes und FontSize sind Eigenschaftsattribute. Sie sind Eigenschaften, die als XML-Attribute ausgedrückt werden Xamarin.Forms .
  • In diesem endgültigen Codeausschnitt TextColor wurde es zu einem Eigenschaftselement. Es handelt sich um eine Xamarin.Forms Eigenschaft, aber es handelt sich jetzt um ein XML-Element.

Die Definition von Eigenschaftselementen scheint zunächst eine Verletzung der XML-Syntax zu sein, aber nicht. Der Punkt hat keine besondere Bedeutung in XML. Bei einem XML-Decoder Label.TextColor handelt es sich einfach um ein normales untergeordnetes Element.

In XAML ist diese Syntax jedoch sehr speziell. Eine der Regeln für Eigenschaftselemente besteht darin, dass im Tag nichts anderes angezeigt werden Label.TextColor kann. Der Wert der Eigenschaft wird immer als Inhalt zwischen den Start- und Endtags des Eigenschaftselements definiert.

Sie können eigenschaftselementsyntax für mehrere Eigenschaften verwenden:

<Label Text="Hello, XAML!"
       VerticalOptions="Center">
    <Label.FontAttributes>
        Bold
    </Label.FontAttributes>
    <Label.FontSize>
        Large
    </Label.FontSize>
    <Label.TextColor>
        Aqua
    </Label.TextColor>
</Label>

Sie können auch die Eigenschaftenelementsyntax für alle Eigenschaften verwenden:

<Label>
    <Label.Text>
        Hello, XAML!
    </Label.Text>
    <Label.FontAttributes>
        Bold
    </Label.FontAttributes>
    <Label.FontSize>
        Large
    </Label.FontSize>
    <Label.TextColor>
        Aqua
    </Label.TextColor>
    <Label.VerticalOptions>
        Center
    </Label.VerticalOptions>
</Label>

Zunächst mag die Syntax von Eigenschaftselement wie ein unnötiger langer Ersatz für etwas vergleichsweise einfaches aussehen, und in diesen Beispielen ist das sicherlich der Fall.

Eigenschaftselementsyntax wird jedoch wesentlich, wenn der Wert einer Eigenschaft zu komplex ist, um als einfache Zeichenfolge ausgedrückt zu werden. Innerhalb der Eigenschaftselement-Tags können Sie ein anderes Objekt instanziieren und dessen Eigenschaften festlegen. Sie können z. B. eine Eigenschaft explizit festlegen, z VerticalOptions . B. auf einen LayoutOptions Wert mit Eigenschafteneinstellungen:

<Label>
    ...
    <Label.VerticalOptions>
        <LayoutOptions Alignment="Center" />
    </Label.VerticalOptions>
</Label>

Ein weiteres Beispiel: Die Grid beiden Eigenschaften haben den Namen RowDefinitions und ColumnDefinitions. Diese beiden Eigenschaften sind vom Typ RowDefinitionCollection und ColumnDefinitionCollection, die Auflistungen und RowDefinitionColumnDefinition Objekte sind. Zum Festlegen dieser Auflistungen müssen Sie die Eigenschaftselementsyntax verwenden.

Dies ist der Anfang der XAML-Datei für eine GridDemoPage Klasse mit den Eigenschaftselementtags für die RowDefinitions und ColumnDefinitions Sammlungen:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.GridDemoPage"
             Title="Grid Demo Page">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="100" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="100" />
        </Grid.ColumnDefinitions>
        ...
    </Grid>
</ContentPage>

Beachten Sie die gekürzte Syntax zum Definieren von Zellen mit automatischer Größe, Zellen mit Pixelbreiten und -höhen sowie Sterneinstellungen.

Angefügte Eigenschaften

Sie haben gerade gesehen, dass für die Grid Eigenschaftenelemente und RowDefinitionsColumnDefinitions Auflistungen die Zeilen und Spalten definiert werden müssen. Es muss jedoch auch eine Möglichkeit für den Programmierer geben, die Zeile und Spalte anzugeben, in der sich jedes untergeordnete Element der Grid Datei befindet.

Innerhalb des Tags für jedes untergeordnete Element der Grid Von Ihnen angegebenen Zeile und Spalte dieses untergeordneten Elements mit den folgenden Attributen:

  • Grid.Row
  • Grid.Column

Die Standardwerte dieser Attribute sind 0. Sie können auch angeben, ob ein untergeordnetes Element mehrere Zeilen oder Spalten mit diesen Attributen umfasst:

  • Grid.RowSpan
  • Grid.ColumnSpan

Diese beiden Attribute weisen Standardwerte von 1 auf.

Hier ist die vollständige Datei "GridDemoPage.xaml":

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.GridDemoPage"
             Title="Grid Demo Page">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="100" />
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="100" />
        </Grid.ColumnDefinitions>

        <Label Text="Autosized cell"
               Grid.Row="0" Grid.Column="0"
               TextColor="White"
               BackgroundColor="Blue" />

        <BoxView Color="Silver"
                 HeightRequest="0"
                 Grid.Row="0" Grid.Column="1" />

        <BoxView Color="Teal"
                 Grid.Row="1" Grid.Column="0" />

        <Label Text="Leftover space"
               Grid.Row="1" Grid.Column="1"
               TextColor="Purple"
               BackgroundColor="Aqua"
               HorizontalTextAlignment="Center"
               VerticalTextAlignment="Center" />

        <Label Text="Span two rows (or more if you want)"
               Grid.Row="0" Grid.Column="2" Grid.RowSpan="2"
               TextColor="Yellow"
               BackgroundColor="Blue"
               HorizontalTextAlignment="Center"
               VerticalTextAlignment="Center" />

        <Label Text="Span two columns"
               Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2"
               TextColor="Blue"
               BackgroundColor="Yellow"
               HorizontalTextAlignment="Center"
               VerticalTextAlignment="Center" />

        <Label Text="Fixed 100x100"
               Grid.Row="2" Grid.Column="2"
               TextColor="Aqua"
               BackgroundColor="Red"
               HorizontalTextAlignment="Center"
               VerticalTextAlignment="Center" />

    </Grid>
</ContentPage>

Die Grid.Row Einstellungen Grid.Column von 0 sind nicht erforderlich, werden jedoch in der Regel für Klarheitszwecke berücksichtigt.

So sieht es aus:

Rasterlayout

Die Beurteilung ausschließlich aus der Syntax, diesen Grid.Row, , Grid.ColumnGrid.RowSpan, und Grid.ColumnSpan Attributen scheinen statische Felder oder Eigenschaften von Grid, aber interessant genug, Grid definiert nichts benanntRow, , ColumnRowSpan, oder ColumnSpan.

Grid Definiert stattdessen vier bindbare Eigenschaften namens RowProperty, , ColumnProperty, RowSpanPropertyund ColumnSpanProperty. Hierbei handelt es sich um spezielle Typen von bindungsfähigen Eigenschaften, die als angefügte Eigenschaften bezeichnet werden. Sie werden durch die Klasse Grid definiert, aber auf untergeordnete Elemente der Klasse Grid gesetzt.

Wenn Sie diese angefügten Eigenschaften im Code verwenden möchten, stellt die Grid Klasse statische Methoden namens SetRow, GetColumnusw. bereit. In XAML werden diese angefügten Eigenschaften jedoch als Attribute in den untergeordneten Elementen der Grid Verwendung einfacher Eigenschaftennamen festgelegt.

Angefügte Eigenschaften sind in XAML-Dateien immer als Attribute erkennbar, die sowohl eine Klasse als auch einen Eigenschaftsnamen enthalten, die durch einen Punkt getrennt sind. Sie werden angehängte Eigenschaften genannt, weil sie von einer Klasse (in diesem Fall Grid) definiert werden, aber an andere Objekte (in diesem Fall untergeordnete Elemente der Grid) angehängt sind. Während des Layouts kann Grid die Werte dieser angehängten Eigenschaften abfragen, um zu wissen, wo jedes untergeordnete Element platziert werden soll.

Die AbsoluteLayout Klasse definiert zwei angefügte Eigenschaften namens LayoutBounds und LayoutFlags. Hier ist ein Checkerboardmuster, das mithilfe der proportionalen Positionierungs- und Größenanpassungsfeatures AbsoluteLayoutrealisiert wird:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.AbsoluteDemoPage"
             Title="Absolute Demo Page">

    <AbsoluteLayout BackgroundColor="#FF8080">
        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="0.33, 0, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="1, 0, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="0, 0.33, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="0.67, 0.33, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="0.33, 0.67, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="1, 0.67, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="0, 1, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="0.67, 1, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

  </AbsoluteLayout>
</ContentPage>

Und so sieht die Ausgabe aus:

Absolutes Layout

Für etwas ähnliches könnten Sie die Weisheit der Verwendung von XAML in Frage stellen. Sicherlich schlägt die Wiederholung und Regelmäßigkeit des LayoutBounds Rechtecks vor, dass es im Code besser realisiert werden könnte.

Das ist sicherlich ein berechtigtes Anliegen, und es besteht kein Problem beim Ausgleich der Verwendung von Code und Markup beim Definieren Ihrer Benutzeroberflächen. Es ist einfach, einige der visuellen Elemente in XAML zu definieren und dann den Konstruktor der CodeBehind-Datei zu verwenden, um einige weitere visuelle Elemente hinzuzufügen, die in Schleifen besser generiert werden können.

Content-Eigenschaften

In den vorherigen Beispielen werden die StackLayoutObjekte Gridund AbsoluteLayout die Eigenschaft des ContentPageLayouts auf die Content Eigenschaft festgelegt, und die untergeordneten Elemente dieser Layouts sind tatsächlich Elemente in der Children Auflistung. Content Diese und Children Eigenschaften befinden sich in der XAML-Datei jedoch nirgendwo.

Sie können die Content Eigenschaften Children und Eigenschaften sicherlich als Eigenschaftselemente einschließen, z. B. im XamlPlusCode-Beispiel :

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.XamlPlusCodePage"
             Title="XAML + Code Page">
    <ContentPage.Content>
        <StackLayout>
            <StackLayout.Children>
                <Slider VerticalOptions="CenterAndExpand"
                        ValueChanged="OnSliderValueChanged" />

                <Label x:Name="valueLabel"
                       Text="A simple Label"
                       FontSize="Large"
                       HorizontalOptions="Center"
                       VerticalOptions="CenterAndExpand" />

                <Button Text="Click Me!"
                      HorizontalOptions="Center"
                      VerticalOptions="CenterAndExpand"
                      Clicked="OnButtonClicked" />
            </StackLayout.Children>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Die eigentliche Frage ist: Warum sind diese Eigenschaftselemente in der XAML-Datei nicht erforderlich?

Für die Verwendung in XAML definierte Xamarin.Forms Elemente dürfen im Attribut der Klasse eine Eigenschaft gekennzeichnet ContentProperty sein. Wenn Sie den Kurs in der ContentPage Onlinedokumentation Xamarin.Forms nachschlagen, wird dieses Attribut angezeigt:

[Xamarin.Forms.ContentProperty("Content")]
public class ContentPage : TemplatedPage

Dies bedeutet, dass die Content Eigenschaftselementtags nicht erforderlich sind. Alle XML-Inhalte, die zwischen den Start- und Endtags ContentPage angezeigt werden, werden der Content Eigenschaft zugewiesen.

StackLayoutAbsoluteLayout, Grid, und RelativeLayout alle abgeleitet von Layout<View>, und wenn Sie in der Xamarin.Forms Dokumentation nachschlagenLayout<T>, wird ein weiteres ContentProperty Attribut angezeigt:

[Xamarin.Forms.ContentProperty("Children")]
public abstract class Layout<T> : Layout ...

Dadurch kann der Inhalt des Layouts automatisch ohne explizite Children Eigenschaftselementtags der Children Auflistung hinzugefügt werden.

Andere Klassen weisen ContentProperty auch Attributdefinitionen auf. Die Inhaltseigenschaft von Label ist zum Beispiel Text. Überprüfen Sie die API-Dokumentation für andere.

Plattformunterschiede mit OnPlatform

In Einzelseitenanwendungen ist es üblich, die Padding Eigenschaft auf der Seite festzulegen, um zu vermeiden, dass die iOS-Statusleiste überschrieben wird. Im Code können Sie die Device.RuntimePlatform Eigenschaft für diesen Zweck verwenden:

if (Device.RuntimePlatform == Device.iOS)
{
    Padding = new Thickness(0, 20, 0, 0);
}

Sie können in XAML auch ähnliche Aktionen ausführen, indem Sie die OnPlatform Klassen verwenden On . Fügen Sie zuerst Eigenschaftenelemente für die Padding Eigenschaft am oberen Rand der Seite ein:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>

    </ContentPage.Padding>
    ...
</ContentPage>

Fügen Sie innerhalb dieser Tags ein Tag hinzu OnPlatform . OnPlatform ist eine generische Klasse. In diesem Fall müssen Sie das generische Typargument angeben, Thicknessbei dem es sich um den Eigenschaftentyp Padding handelt. Glücklicherweise gibt es ein XAML-Attribut speziell, um generische Argumente zu definieren, die aufgerufen werden x:TypeArguments. Dies sollte mit dem Typ der Eigenschaft übereinstimmen, die Sie festlegen:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">

        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

OnPlatformverfügt über eine Eigenschaft mit dem Namen Platforms eines OnIList Objekts. Verwenden Sie Eigenschaftselementtags für diese Eigenschaft:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <OnPlatform.Platforms>

            </OnPlatform.Platforms>
        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

Fügen Sie nun Elemente hinzu On . Legen Sie für jede Eigenschaft die Platform Eigenschaft und die Value Eigenschaft auf Markup für die Thickness Eigenschaft fest:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <OnPlatform.Platforms>
                <On Platform="iOS" Value="0, 20, 0, 0" />
                <On Platform="Android" Value="0, 0, 0, 0" />
                <On Platform="UWP" Value="0, 0, 0, 0" />
            </OnPlatform.Platforms>
        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

Dieses Markup kann vereinfacht werden. Die Inhaltseigenschaft OnPlatform lautet Platforms, sodass diese Eigenschaftselementtags entfernt werden können:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <On Platform="iOS" Value="0, 20, 0, 0" />
            <On Platform="Android" Value="0, 0, 0, 0" />
            <On Platform="UWP" Value="0, 0, 0, 0" />
        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

Die Platform Eigenschaft des On Typs IList<string>ist, sodass Sie mehrere Plattformen einschließen können, wenn die Werte gleich sind:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <On Platform="iOS" Value="0, 20, 0, 0" />
            <On Platform="Android, UWP" Value="0, 0, 0, 0" />
        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

Da Android und UWP auf den Standardwert Paddingfestgelegt sind, kann dieses Tag entfernt werden:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <On Platform="iOS" Value="0, 20, 0, 0" />
        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

Dies ist die Standardmethode zum Festlegen einer plattformabhängigen Padding-Eigenschaft in XAML. Wenn die Value Einstellung nicht durch eine einzelne Zeichenfolge dargestellt werden kann, können Sie Eigenschaftenelemente dafür definieren:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <On Platform="iOS">
                <On.Value>
                    0, 20, 0, 0
                </On.Value>
            </On>
        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

Hinweis

Die OnPlatform Markuperweiterung kann auch in XAML verwendet werden, um die Darstellung der Benutzeroberfläche pro Plattform anzupassen. Sie bietet die gleiche Funktionalität wie die Klassen OnPlatform und On, jedoch mit einer prägnanteren Darstellung. Weitere Informationen finden Sie unter OnPlatform-Markuperweiterung.

Zusammenfassung

Mit Eigenschaftenelementen und angefügten Eigenschaften wurde ein Großteil der grundlegenden XAML-Syntax erstellt. Manchmal müssen Sie jedoch Eigenschaften auf Objekte indirekt festlegen, z. B. aus einem Ressourcenverzeichnis. Dieser Ansatz wird im nächsten Teil, Teil 3, behandelt. XAML-Markuperweiterungen.