BackacheEngineerの技術的な備忘録

技術系でいろいろ書けたらなーと

XAML: データバインディング時の変換器(Converter) について

XAMLで値を変換しながらバインディングするための変換器であるConverterについてまとめる。 データバインディングは過去記事にちょこっとまとめた。

backacheengineer.hatenablog.com

Converterの使いどころ

使いどころは値を変換したいとき(当たり前)だ。 例えば、int 型の値を16進数下2桁で表示したいときなどに、内部で「変数.ToString("X2")」みたいなのができる。 正直なところ、使いまくるということはないと思っている。

Converterクラスの実装

実装は「IValueConverter」インターフェースを継承して行う。 サクッとサンプルをば。

    public class FormattedStringConverter : IValueConverter
    {
        /// <summary>
        /// 変換してバインディング(バインディングソースが変換されるはず。つまり OneWay 方向)
        /// </summary>
        /// <param name="value">バインディングソースの値</param>
        /// <param name="targetType">バインディングターゲットのタイプ</param>
        /// <param name="parameter">Convert時の引数</param>
        /// <param name="culture">CultuerInfo、使用する暦とか、日付とか数値の書式がつまってる。</param>
        /// <returns>変換後の値</returns>
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            // ソースが書式変換できるやつで、
            // 書式が引数で指定されてて
            // ターゲットが文字列のとき
            if (value is IFormattable && parameter is string && 
                string.IsNullOrEmpty(parameter as string) == false &&
                targetType == typeof(string))
            {
                return (value as IFormattable).ToString(parameter as string, culture);
            }
            return value;
        }
        /// <summary>
        /// 変換してバインディング(バインディングターゲットが変換されるはず。使ったことない!!)
        /// </summary>
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }
    }

これを、XAML側でこう使う。 Windowの横幅をTextBlockにバインディングバインディングするとき、上記のConverterを使って値を「ToString("N0")」で変換している。 「N0」は小数点以下0桁で、桁数にカンマ入れてくれる(1200.001 とかは 1,200 になる)。

<Window ...
    <Window.Resources>
        <local:FormattedStringConverter x:Key="stringConverter"/>
    </Window.Resources>

...

    <TextBlock Text="{Binding ElementName=window, Path=ActualWidth, Converter={StaticResource stringConverter}, ConverterParameter=N0}"/>
</Window>