rksoftware

Visual Studio とか C# とかが好きです

Xamarin Forms で XAML を使わず開発する

Xamarin.Forms は (少なくとも大抵のチュートリアルなどでは) XAML で UI を構築しています。
しかし、XAML でなければ UI を構築できないというわけではありません。XAML が良くわからなければ、C# コードで UI を構築することもできます。
雑に説明すれば、Xamarin.Forms は UI 要素を階層化された構造で構築します。XAML はこの構築の構造を記述しているだけなので、C# で直接 UI 要素を生成するコードを書いても同じ結果になります。

■ テンプレートで生まれる XAML

まずは、テンプレートで生まれる XAML を見てみましょう。
ContentPage のコンテンツとして StackLayout があり、その StackLayout の子として Label がある、という UI を構築する定義になっています。

<?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:App1"
             x:Class="App1.MainPage">

    <StackLayout>
        <!-- Place new controls here -->
        <Label Text="Welcome to Xamarin.Forms!" 
           HorizontalOptions="Center"
           VerticalOptions="CenterAndExpand" />
    </StackLayout>

</ContentPage>

・実行結果

これと同じものを C# コードで構築しましょう。

■ C# で UI を構築するページの生成

  • ソリューションエクスプローラーで マウス右クリック します。
  • 追加 > 新しい項目の追加 を選択します。
  • 表示されるダイアログの左のペインで Visual C# アイテム > Xamarin.Forms を選択します。
  • 中央のペインで コンテンツ ページ (C#) を選択します。

次の様なクラスが生成されます。

using Xamarin.Forms;

namespace App1
{
    public class Page1 : ContentPage
    {
        public Page1 ()
        {
            Content = new StackLayout {
                Children = {
                    new Label { Text = "Welcome to Xamarin.Forms!" }
                }
            };
        }
    }
}

■ メインページの変更

アプリ実行時にプロジェクトに追加した新しいページを表示するには App.xaml.cs の編集が必要です。 テンプレートから生まれた App.xaml.cs は次のようになっています。

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace App1
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();

            MainPage = new MainPage();
        }

        protected override void OnStart()
        {
        }

        protected override void OnSleep()
        {
        }

        protected override void OnResume()
        {
        }
    }
}

この

MainPage = new MainPage();

の部分で MainPage プロパティに代入されているページが、アプリ実行時に表示されます。
今回は新しく作ったページ (例: Page1) に変更します。

MainPage = new Page1();

変更後の App.xaml.cs は次のようになります。

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace App1
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();

            MainPage = new Page1();
        }

        protected override void OnStart()
        {
        }

        protected override void OnSleep()
        {
        }

        protected override void OnResume()
        {
        }
    }
}

■ 実行

実行すると次の様に表示され、追加した新しいページが表示されていることがわかります。

XAML の時と少し表示が異なっています。折角なので、同じ表示になるよう変更してみましょう。

■ C# コードの変更

Page1 では XAML で書かれた MainPageLabel に設定されていたプロパティのうち HorizontalOptionsVerticalOptions の二つのプロパティが設定されていません。
これらを C# コードで設定してみます。

using Xamarin.Forms;

namespace App1
{
    public class Page1 : ContentPage
    {
        public Page1()
        {
            Content = new StackLayout
            {
                Children = {
                    new Label { Text = "Welcome to Xamarin.Forms!" ,
                        HorizontalOptions = LayoutOptions.Center,
                        VerticalOptions = LayoutOptions.CenterAndExpand
                    }
                }
            };
        }
    }
}

■ 実行

実行すると次のように表示され、XAML の時と同じ表示になることがわかります。
]

このように XAML で書いたものと同じものが C# コードでも作れます。
XAML がなじまない場合は C# コードで UI を記述しても大丈夫です。好きな方を選択してください。
※ただし、一つのチームでメンバーごとに違うスタイルを選択することはお勧めできません。個人ごとではなくチームで統一することをお勧めします。

■ 補足 Content プロパティと Children プロパティ

Xamarin.Forms では UI は階層化された構造を持ちます。そのため基本的に UI 要素は何らかの親子関係を持つことになります。
この親子関係を作るプロパティが Content プロパティと Children プロパティです。親要素の Content または Children プロパティに子要素を設定することで親子構造を構築します。

ContentChildren の違い

雑に言えば、子要素を一つだけ持つ要素は Content プロパティを持ち、子要素を複数持つ場合は Children プロパティです。
ここで一つだけ/複数というのは子要素の数で考えます。孫要素などの子孫要素のことは考えません。
例えば前述の Page1 の場合、子要素は一つしか持てません。例では StackLayout 要素一つを持っています。この StackLayout 要素はさらに子要素として Label 要素を持っていますが、これは孫要素ということになります。子孫全体でいえば二つ(以上)の要素を持てると言えますが、孫以降の要素は考えないため子要素の上限数 (ひとつ) だけということになります。
結果として Page1 のプロパティは Content プロパティということになります。

■ 得意な方法で開発を

XAML と C# のどちらで記述しても構いません。XAML の方が情報は多いですが、XAML がなじまないというだけで Xamarin.Forms をあきらめてしまうのはもったいないです。
XAML がなじまない方も、C# コードで Xamarin.Forms を継続してみてください。