レガシーコードからの脱却

レガシーな職場でも独学でどうにか頑張っていくブログです。

【お勉強記録】WPFデータバインディング2

コンバーター

データバインド「もと」と「さき」で異なる型になる場合があると思います。 例えば、Textプロパティに対して日付型をバインドした場合、日付型をToString()形で自動変換されたものが表示されます。

f:id:Gappory:20170721215128p:plain

前回の例でいうとDateTime型の「誕生日」はToString()された状態で表示されていたため、日本で一般的な表記ではありませんでした。

型コンバータを使うことで、「さき」と「もと」で相互の型変換を行うことができます。 型コンバータは「IValueConverter」を実装することで使用できます。

「IValueConverter」は、以下の2つのメソッド定義を持っています。

 // 概要:
    //     カスタム ロジックをバインディングに適用する方法を提供します。
    public interface IValueConverter
    {
        // 概要:
        //     値を変換します。
        //
        // パラメーター:
        //   value:
        //     バインディング ソースによって生成された値。
        //
        //   targetType:
        //     バインディング ターゲット プロパティの型。
        //
        //   parameter:
        //     使用するコンバーター パラメーター。
        //
        //   culture:
        //     コンバーターで使用するカルチャ。
        //
        // 戻り値:
        //     変換された値。 メソッドが null を返す場合は、有効な null 値が使用されています。
        object Convert(object value, Type targetType, object parameter, CultureInfo culture);
        //
        // 概要:
        //     値を変換します。
        //
        // パラメーター:
        //   value:
        //     バインディング ターゲットによって生成される値。
        //
        //   targetType:
        //     変換後の型。
        //
        //   parameter:
        //     使用するコンバーター パラメーター。
        //
        //   culture:
        //     コンバーターで使用するカルチャ。
        //
        // 戻り値:
        //     変換された値。 メソッドが null を返す場合は、有効な null 値が使用されています。
        object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture);
    }

メソッド名を見れば大体想像できますが、Convert()はバインド「もと」から「さき」へ値を渡すときの変換を、ConvertBack()は「さき」から「もと」の変換を実装しているようです。

DateTimeの型コンバータの実装

using System;
using System.Globalization;
using System.Windows.Data;

namespace _0721Study
{
    [ValueConversion(typeof(DateTime), typeof(string))]
    class DateTimeConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            DateTime date = (DateTime)value;
            return date.ToString(parameter.ToString());
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string strValue = value.ToString();
            DateTime resultDateTime;
            if (DateTime.TryParse(strValue, out resultDateTime))
            {
                return resultDateTime;
            }
            return value;
        }
    }
}

Convert()メソッドは受け取った値をparameterをもとにstringに変換して返しています。 ConvertBack()メソッドはstringをDateTime型に変換して返します。

xaml側を書きます。

<Window x:Class="_0721Study.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:_0721Study"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:User x:Key="oUser"
                       Name="山田 太郎"
                       Birthday="1990/07/21"/>
        <local:DateTimeConverter x:Key="dateTimeConverter" />
    </Window.Resources>
    <WrapPanel Orientation="Horizontal" DataContext="{StaticResource oUser}">
        <Label Content="名前:"  VerticalAlignment="Center" ></Label>
        <TextBlock Text="{Binding Path=Name}" VerticalAlignment="Center"></TextBlock>
        <Label Content="誕生日:"  VerticalAlignment="Center" ></Label>
        <TextBlock Text="{Binding Path=Birthday, Converter={StaticResource dateTimeConverter},ConverterParameter=yyyy/MM/dd}" VerticalAlignment="Center"></TextBlock>
    </WrapPanel>
</Window>

BindingでConverterにlocal:DateTimeConverter のオブジェクトと、ConverterParameterを指定しています。

f:id:Gappory:20170722094059p:plain

実行結果を見ると誕生日がしっかり、日本人になじみのある形に変換されているのが確認できました!