DelegateConverter みたいなもの

一箇所でしか使わないのに、わざわざコンバーターを作成するなんて面倒。変換メソッドを外部から設定できる、DelegateConverter クラスがあれば便利です。

public class DelegateConverter : IValueConverter
{
    public event EventHandler<ConvertEventArgs> OnConvert;
    public event EventHandler<ConvertEventArgs> OnConvertBack;

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var e = new ConvertEventArgs(value, targetType, parameter, culture);
        var handler = OnConvert;
        if (handler != null)
        {
            handler(this, e);
        }
        return e.ReturnValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var e = new ConvertEventArgs(value, targetType, parameter, culture);
        var handler = OnConvertBack;
        if (handler != null)
        {
            handler(this, e);
        }
        return e.ReturnValue;
    }
}

public class ConvertEventArgs : EventArgs
{
    public ConvertEventArgs(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Value = value;
        TargetType = targetType;
        Parameter = parameter;
        Culture = culture;
        ReturnValue = value;
    }
    public object Value { get; private set; }
    public Type TargetType { get; private set; }
    public object Parameter { get; private set; }
    public CultureInfo Culture { get; private set; }
    public object ReturnValue { get; set; } // 変換した値
}

使い方はこんな感じ。

<Window x:Class="DelegateConverterSample.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:DelegateConverterSample"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <local:DelegateConverter x:Key="NameConverter"
                                 OnConvert="DelegateConverter_OnConvert"
                                 OnConvertBack="DelegateConverter_OnConvertBack"/>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Label Content="名前"
               Grid.Column="0"/>
        <TextBox Text="{Binding Path=Name, Converter={StaticResource NameConverter}}"
                 Grid.Column="1"/>
    </Grid>
</Window>

このサンプルでは、変換メソッドの設定に仕方なくイベントを使っています。本当は Func を使いたかったんですけど、それだと XAML で設定したメソッドを Func に変換できないので…。

Func 変換用のコンバーターを作るのは本末転倒ですよね。コンバーターを使うためのコンバーターって、変。