パート 2. 基本的な XAML 構文

 

パート 2. 基本的な XAML 構文

プロパティ要素とアタッチ プロパティ

XAML は、主にオブジェクトのインスタンス化と初期化のために設計されたものです。しかし、プロパティを XML 文字列として簡単に表現できない複雑なオブジェクトに設定する場合や、1 つのクラスで定義されたプロパティを子クラスに設定する場合もあります。これらの場合、本質的な XAML 構文機能 (プロパティ要素とアタッチ プロパティ) が必要になります。

 

プロパティ要素

XAML では、クラスのプロパティは XML 属性として通常設定されます。

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

しかし、XAML でプロパティを設定する別の方法もあります。この別の方法を TextColor で試してみましょう。まず、既存の TextColor 設定を削除します。

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

Label タグを開始タグと終了タグに分割して、空の要素を追加します。

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

</Label>

これらのタグ内に、クラス名とプロパティ名がピリオドで区切られた開始タグと終了タグを追加します。

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

  </Label.TextColor>
</Label>

これらの新しいタグのコンテンツとしてプロパティ値を設定します。

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

これらの TextColor プロパティを指定する 2 つの方法は機能的には等価ですが、プロパティを 2 回設定するため、同じプロパティに両方の方法を使用することはできません。

この新しい構文では、いくつかの用語が導入されています。

  • Labelオブジェクト要素 です。これは XML 要素として表現された Xamarin.Forms オブジェクトです。
  • TextVerticalOptionsFontAttributes および FontSizeプロパティ属性 です。これらは XML 属性として表現された Xamarin.Forms プロパティです。
  • 最後のコードの TextColorプロパティ要素 です。これは Xamarin.Forms プロパティですが、XML 要素でもあります。

プロパティ要素の定義は XML 構文に違反しているように見えるかもしれませんが、違反ではありません。ピリオドは XML では特別な意味はありません。XML である限り、Label.TextColor は通常の子要素に過ぎません。

しかし、XAML では、この構文は非常に特殊です。プロパティ要素の規則の 1 つは、Label.TextColor タグ中に他のものが現れないことです。プロパティの値は、プロパティ要素の開始タグと終了タグの間のコンテンツとして常に定義します。

複数のプロパティにプロパティ要素構文を使用できます。

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

すべてのプロパティにプロパティ要素構文を使用してもかまいません。

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

始めは、プロパティ要素構文は比較的単純なものを長いものに置き換える無駄なものに見えるかもしれません。ここの例では、その考えは正解です。

しかし、プロパティの値が複雑すぎて単純な文字列として表現できない場合、プロパティ要素構文は不可欠になります。プロパティ要素タグ内では、別のオブジェクトをインスタンス化してそのプロパティを設定することができます。例えば、VerticalOptions のようなプロパティを LayoutOptions 値とプロパティ設定に明示的に設定できます。

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

別の例: Grid には RowDefinitions および ColumnDefinitions の 2 つのプロパティがあります。これらの 2 つのプロパティは RowDefinitionCollection および ColumnDefinitionCollection 型で、RowDefinition および ColumnDefinition オブジェクトのコレクションです。コレクションに行と列の次元をすべて単一文字列として定義する構文がない限り (可能ですがありません)、プロパティ要素構文が必要になります。

GridDemoPage クラスの XAML ファイルの先頭部分 (RowDefinitions および ColumnDefinitions コレクションのプロパティ要素タグを含む) を次に示します。

<?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="XamlSamples.GridDemoPage"
             Title="Grid Demo Page"
             Padding="0, 20, 0, 0">

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

自動サイズのセル、セルのピクセル幅と高さ、および * 設定を定義する構文は省略されていることに注意してください。

この XAML 部分には、プロパティ要素の別の潜在的な用途も含まれています。ContentPage タグの Padding は上が 20 ユニットに設定されていますが、これは iPhone でステータス バーがオーバーラップしないようにするためです。このパディングは Android および Windows Phone では必要ありません。(XamlSamples のページのように、ページを NavigationPage でナビゲートする場合にも必要ありませんが、単一ページ アプリケーションのスタンドアロン ページであるものとして続けます。)

幸い、OnPlatform<T> クラスを使用して、XAML ファイルにプラットフォーム固有のマークアップを埋め込む方法があります。これは、T 型の iOSAndroid、および WinPhone の 3 つのプロパティを含む汎用クラスです。OnPlatform<T> クラスは、実行しているプラットフォームに応じて適切なオブジェクトを返す、T 型の暗黙のキャストも定義します。

一見複雑そうに感じられますが、XAML 構文は非常に単純です。まず、PaddingContentPage クラスの要素として分離します。

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

  <ContentPage.Padding>
    0, 20, 0, 0
  </ContentPage.Padding>

  ...

</ContentPage>

他の変更はありません。次に、ContentPage.Padding タグのコンテンツを OnPlatform タグに置換します。OnPlatform は汎用クラスであることに注意してください。ここでは、汎用型引数 Thickness (Padding プロパティの型) を指定する必要があります。幸い、汎用引数 x:TypeArguments とともに使用する特別な 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">

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

    ...

    </OnPlatform>
  </ContentPage.Padding>

  …

</ContentPage>

OnPlatform タグ間に、各プラットフォームの Padding 値を含む、iOSAndroid、および WinPhones プロパティの 3 つのプロパティ要素タグを追加します。

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

  <ContentPage.Padding>
    <OnPlatform x:TypeArguments="Thickness">
      <OnPlatform.iOS>
        0, 20, 0, 0
      </OnPlatform.iOS>
      <OnPlatform.Android>
        0, 0, 0, 0
      </OnPlatform.Android>
      <OnPlatform.WinPhone>
        0, 0, 0, 0
      </OnPlatform.WinPhone>
    </OnPlatform>
  </ContentPage.Padding>

  ...

</ContentPage>

個々のプロパティ要素のコンテンツを単純な文字列で表すことができれば (できます)、代わりにプロパティ属性として定義することができます。

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

  <ContentPage.Padding>
    <OnPlatform x:TypeArguments="Thickness"
                iOS="0, 20, 0, 0"
                Android="0, 0, 0, 0"
                WinPhone="0, 0, 0, 0" />
  </ContentPage.Padding>

  ...

</ContentPage>

ただし、Android および Windows Phone の値は Padding のデフォルトであるため、これらの 2 つの属性設定は削除できます。

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

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

  ...

</ContentPage>

これは、iPhone のステータス バーをオーバーラップしないようにするため ContentPage で使用できる標準マークアップです。

(前述したように、ダウンロード可能な XamlSamples ソリューションでは、これらの個々のページは NavigationPage でナビゲートされるため、このパディングは必要ありません。iPhone のステータス バーは自動的に考慮されます。)

 

アタッチ プロパティ

これまで説明したように、Grid には、行と列を定義する RowDefinitions および ColumnDefinitions コレクションのプロパティ要素が必要です。しかし、Grid の子が存在する場所では、プログラマが行と列を示す別の方法があります。

Grid の子のタグ内では、次の属性を使用して、子の行と列を指定します。

  • Grid.Row
  • Grid.Column

これらの属性のデフォルト値は 0 です。また、次の属性を使用して、子が行または列を 2 つ以上に分割するかどうか示すことができます。

  • Grid.RowSpan
  • Grid.ColumnSpan

これらの属性のデフォルト値は 1 です。

GridDemoPage.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"
             x:Class="XamlSamples.GridDemoPage"
             Title="Grid Demo Page">

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

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

Grid.Row および Grid.Column の 0 の設定は必要ありませんが、分かりやすく説明するために追加しています。

3 つのプラットフォームの結果は次のようになります。

構文から判断すると、Grid.RowGrid.ColumnGrid.RowSpan、および Grid.ColumnSpan 属性は Grid のスタティック フィールドまたはプロパティのように見えますが、GridRowColumnRowSpan、または ColumnSpan の何も定義していません。

代わりに、GridRowPropertyColumnPropertyRowSpanProperty、および ColumnSpanProperty の 4 つのバインド可能なプロパティを定義しています。これらは、アタッチ プロパティ と呼ばれる、特別な種類のバインド可能なプロパティです。これらのアタッチ プロパティは Grid クラスで定義されますが、Grid の子で設定されます。

コードでこれらのアタッチ プロパティを使用する場合、Grid クラスは SetRowGetColumn などのスタティック メソッドを提供します。しかし、XAML では、これらのアタッチ プロパティは単純なプロパティ名を使用して Grid の子の属性として設定されます。

アタッチ プロパティは、ピリオドで区切られたクラス名とプロパティ名を含む属性として XAML ファイルで常に識別可能です。これらは 1 つのクラス (この場合は Grid) で定義されますが、他のオブジェクト (この場合は Grid の子) にアタッチされるため、アタッチ プロパティ と呼ばれます。レイアウト中に、Grid は、これらのアタッチ プロパティの値を確認して子を配置する場所を知ります。

AbsoluteLayout クラスは 2 つのアタッチ プロパティ LayoutBounds および LayoutFlags を定義します。AbsoluteLayout の比例位置設定およびサイズ設定機能を使用して実現されたチェス盤のコードを次に示します。

<?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="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>

画面は次のようになります。

このようなケースでは、XAML を使用することを疑問に思われるかもしれません。確かに、LayoutBounds 長方形の反復および規則性は、コードでより適切に実現することができるでしょう。

その疑問は正しいものです。ユーザー インターフェイスを定義するときにコードとマークアップの使用のバランスを取ることに問題はありません。XAML でいくつかのビジュアルを定義した後、分離コード ファイルのコンストラクターを使用して、ループでより適切に生成されるいくつかのビジュアルを追加することは簡単です。

 

Content プロパティ

前の例では、StackLayoutGrid、および AbsoluteLayout オブジェクトが ContentPageContent プロパティに設定され、これらのレイアウトの子は Children コレクションの実際のアイテムでした。しかし、これらの Content および Children プロパティは XAML ファイルに存在していません。

Content および Children プロパティはプロパティ要素として含めることができるはずです。

<?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="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>

なぜこれらのプロパティは XAML ファイルに必要 ない のでしょうか?

XAML で使用するために Xamarin.Forms で定義された要素は、クラスの ContentProperty 属性に 1 つのプロパティ フラグを付けることができます。オンラインの Xamarin.Forms ドキュメントで ContentPage クラスを調べると、この属性の説明が見つかります。

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

これは、Content プロパティ要素タグが必要ないことを意味します。ContentPage の開始タグと終了タグの間に現れる XML コンテンツはすべて、Content プロパティに割り当てられると仮定されています。

StackLayoutGridAbsoluteLayout、および RelativeLayout はすべて Layout<View> から派生します。Xamarin.Forms ドキュメントで Layout<T> を調べると、別の ContentProperty 属性の説明が見つかります。

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

これで、明示的な Children プロパティ要素タグなしで、レイアウトのコンテンツを Children コレクションに自動的に追加することができます。

Xamarin.Forms の ContentProperty 属性の定義は次のとおりです。

要素 Content プロパティ
ContentPage Content
ContentView Content
Frame Content
Label Text
Layout<T> Children
ScrollView Content
ViewCell View

 

まとめ

プロパティ要素とアタッチ プロパティを使用すると、基本的な XAML 構文の多くを確立することができます。しかし、間接的な方法で参照する必要があるオブジェクトのプロパティを設定する場合もあります。このソリューションについては、パート 3. XAML マークアップ拡張で説明します。

 

 


Infragistics Infragistics
エンタープライズ向け統合 UI 開発コンポーネント。WinForms、モバイル、Web 用の UI コントロール。
CData ドライバー CData ドライバー
50 以上のデータ ソースへのアクセスをプログラミングなしで可能にするデータベース ドライバー。
SmartBear Software SmartBear
GUI テスト / プロファイラー / 負荷テスト / API テスト: ソフトウェア テストの自動化/工数削減/品質向上。
/n software IP*Works! /n software IP*Works!
クロスプラットフォーム対応のインターネット アプリケーション開発向けコンポーネント スイート。
UXDivers Grial UI Kit
Xamarin Forms 対応の XAML ベースの UI、UX テンプレートを提供
XFINIUM.PDF XFINIUM.PDF
Xamarin 対応のクロスプラットフォーム PDF 開発ツール
Aspose Aspose
.NET/Java で Word、Excel、PowerPoint、PDF などの Office ファイルを操作できる API ライブラリ。
Visual Studio Microsoft Visual Studio
最新の統合開発環境!アプリケーションの迅速かつ高品質な構築を支援する開発環境を提供。