読者です 読者をやめる 読者になる 読者になる

雑記 - otherwise

最近はDQ10しかやっていないダメ技術者がちまちまと綴る雑記帳

Windows store アプリでバインドのフォーマットを指定する

Win8App C#

Windows store apps Advent Calendar 2012 6 日目です。
エントリーした時は、 1 ヶ月もあればひとつ位アプリを作ってみる時間も取れるだろうと思っていたのですが、予想以上に時間が経つのが早くて、結局ちゃんとしたアプリも作れぬまま順番がまわってきてしまいました。
# せっかく開発者登録も済ませて体制だけは整えたのに。。。
そんな状態でまだあまり実践的な事が出来ていないので、今回は 10 月のわんくま勉強会でデモに使ったサンプルアプリを作る際にちょっとだけ悩んだ事を、備忘録代わりに書いておこうと思います。
WPFSilverlight 等の XAML アプリケーションの開発経験がある方なら、 XAML でのデータバインドの方法についてはご存知の事と思います。
この XAML でのデータバインドは結構強力で、文字列型以外の項目を設定しても、プリミティブ型であれば良しなに型変換を行ってくれます。
# クラスインスタンスや独自型だとそのままではムリなケースが多いですが。
ただ、例えば 数値をカンマ編集したい、 DateTime 型を月日だけ見せたい等、ちょっとフォーマットを変えたいと思う事もあると思います。
そんな時は Binding クラスの StringFormat プロパティの出番(のはず)なのですが、困った事に Windows store アプリ用の .NET ライブラリには StringFormat プロパティがないんですね。。。
ないのは仕方がないですが、さすがにフォーマットした文字列を管理するプロパティを別に作るのは勘弁願いたいので、ここは Converter を利用して対応する事にします。
まずは IValueConverter インターフェース を実装したコンバータクラスを作ります。

using System;
using Windows.UI.Xaml.Data;

namespace AdventCalendar20121206CS
{
    public class DateTimeConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            if (value is DateTime)
            {
                var target = (DateTime)value;
                if (parameter == null)
                {
                    return target.ToString();
                }
                else
                {
                    return target.ToString(parameter.ToString());
                }
            }
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotSupportedException();
        }
    }
}

上記は DateTime 型に対するコンバータの例です。
他の型については別のコンバータを用意してもいいですし、 value の型チェックのところで分岐させてもいいと思います。
# 今回は表示のみを対象としたため string → DateTime? への変換 (ConvertBack) を省略しています。
# Mode=TwoWay な項目に適用する場合は ConvertBack も実装する様にしてください。
次に、このコンバータを XAML でリソースとして登録します。

    <Page.Resources>
        <local:DateTimeConverter x:Key="DateTimeStringFormatConverter"/>
    </Page.Resources>

後は、バインド定義でこのコンバータを指定してあげれば完成です。

        <TextBlock x:Name="sample"
                   Text="{Binding Hoge,
                                  Converter={StaticResource DateTimeStringFormatConverter},
                                  ConverterParameter='MM/dd'}"/>

これで、 Windows store アプリでもバインド時にフォーマットを指定する事が出来る様になります。
コンバータクラスを準備するのは少々面倒ですが、一度作ってライブラリ化してしまえば、後は楽ですね。
# 尤も、フレームワーク側がさっさと StringFormat に対応してくれればそれでいいんですけど。。。

余談

ところで、 Expression Blend で StringFormat の指定が出来ないのは改善されないのでしょうか。。。(何気に毎回手書きで指定するのは面倒><)