rksoftware

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

Xamarin Form で XAML を使わず StringFormat を指定する

以前に Xamarin Form で XAML を使わず DataBinding する記事を書きました。 内容は特に何というわけでもなく、C# コードで UI を構築し DataBinding するものです。
今回はもう少し DataBinding を深堀して StringFormat も指定してみます。

■ 結論

label2.SetBinding(Label.TextProperty, new Binding("FiveThousandTrillion", stringFormat: "{0} 円欲しい"));
label3.SetBinding(Label.TextProperty, new Binding("FiveThousandTrillion", stringFormat: "{0:0,000} 円欲しい"));

この様に書くと StringFormat 付きで DataBindingが設定できます。

以降に XAML で書いた場合とコードで書いた場合の実例を書いてみます。

■ ViewModel

実際の UI の前に ViewModel です。ViewModel は XAML と C# コードで同じものを使います。
FiveThousandTrillion プロパティを持つだけのクラスです。 INotifyPropertyChanged を実装しているためにコードが少しありますが、今回の要点ではないので読み飛ばしてください。

using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace CodeDataBinding
{
    public class CodeBindingViewModel : INotifyPropertyChanged
    {
        public long FiveThousandTrillion { get; } = 50_000_000_000_000_000L;


        // INotifyPropertyChanged のいつものコード

        public event PropertyChangedEventHandler PropertyChanged;

        private bool SetProperty<T>(ref T value, T newValue, [CallerMemberName] string propertyName = null)
        {
            if (object.Equals(value, newValue)) return false;
            value = newValue;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            return true;
        }
    }
}

■ XAML

XAML で書いた場合です。何のこともない良くある Binding です。

<?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:CodeDataBinding"
             x:Class="CodeDataBinding.XamlBindingPage">
    <ContentPage.BindingContext>
        <local:CodeBindingViewModel />
    </ContentPage.BindingContext>
    <StackLayout VerticalOptions="Center">
        <Label Text="{Binding FiveThousandTrillion}" />
        <Label Text="{Binding FiveThousandTrillion, StringFormat='{0} 円欲しい'}" />
        <Label Text="{Binding FiveThousandTrillion, StringFormat='{0:0,000} 円欲しい'}" />
    </StackLayout>
</ContentPage>

二つ目の Label は値の後ろに「 円欲しい」という文字列が付きます。
三つ目の Label はさらに値が「,」で区切られます。

■ コード

C# コードです。コードの下の方で StringFormat 指定付きで DataBinding を設定しています。
Binding クラスのコンストラクタは多くの引数がありますが、一つ目の引数を除いてデフォルト値が設定されています。このような場合、名前付き引数を使うことで設定する引数を選ぶことができます。 stringFormat: となっている部分です。
今回は短く書くためとできることを紹介するために名前付き引数を使っていますが、名前付き引数は使わないで済むならそれに越したことはありません。その場合はオブジェクト初期化しを使って new Binding("FiveThousandTrillion") { StringFormat = "{0:0,000} 円欲しい" } と書いても良いでしょう。
UI コントロールの生成部分が少し重いですが、今回の要点ではないので生成部分は読み飛ばして OK です。

using System;
using Xamarin.Forms;

namespace CodeDataBinding
{
    public class CodeBindingPage : ContentPage
    {
        public CodeBindingPage()
        {
            Label label1, label2, label3;
            Content = new StackLayout
            {
                VerticalOptions= LayoutOptions.Center,
                Children = {
                    (label1 = new Label()),
                    (label2 = new Label()),
                    (label3 = new Label())
                }
            };

            BindingContext = new CodeBindingViewModel();

            label1.SetBinding(Label.TextProperty, new Binding("FiveThousandTrillion"));
            label2.SetBinding(Label.TextProperty, new Binding("FiveThousandTrillion", stringFormat: "{0} 円欲しい"));
            label3.SetBinding(Label.TextProperty, new Binding("FiveThousandTrillion", stringFormat: "{0:0,000} 円欲しい"));
        }
    }
}

結果は XAML と同じなので省略します。

■ 得意な方法で開発を

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