概要
WPFでよく使用するConveter
クラスについて、説明とサンプルコードを簡単にまとめました。
Converter
クラスとは
Converter
クラスは、ViewとViewModel間で異なる型のデータを、互換性のある形式に変換する役割を果たします。たとえば、ViewModelのBool型のデータを、Viewに合わせてVisibility
型に変換するConverterがあるとします。その場合、ViewModelのとあるbool型のデータがtrue
なら、Viewのとあるコントロールを表示、false
ならとあるコントロールを非表示、という実装ができます。
他にも、ViewModelのBool型のデータを、ViewのBrushes
型 (色) に変換するConverterなら、bool型の値に合わせて、Viewのコントロールの色を変更できたりします。
作成方法
Converter
クラスを作る際は、標準ライブラリPresentationFramework.dll
の名前空間System.Windows.Data
にある、インターフェースIValueConverter
をもつのが一般的です。Converter
クラス内にはConvert
メソッドとConvertBack
メソッドを実装します。Convert
メソッドはViewModelのプロパティからViewへの変換を記述し、ConvertBack
メソッドはViewからViewModelのプロパティへの変換を記述します。
ただConvertBack
メソッドは使用しない場合も多いので、
その場合はthrow new NotImplementedException();
等を記述しておきます。
サンプルコード
以下に、いくつかのConverterクラスのサンプルコードをまとめました。
- 1. ViewModelのbool値をViewのVisibilityに変換する
- 2. ViewModelのbool値をViewのstringに変換する
- 3. ConverterParameterの使用例
- 4. ConvertBackの使用例
1. ViewModelのbool
値をViewのVisibility
に変換する
ViewModelのとあるプロパティのbool値がtrue
のときはVisible
、false
のときはCollapsed
に変換するクラスです。
Converter
namespace Hoge.Converters
{
public class BoolToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
try
{
if (value == null || (bool)value == false)
{
return Visibility.Collapsed;
}
else
{
return Visibility.Visible;
}
}
catch (Exception)
{
// エラーのためログ出力
return Visibility.Collapsed;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
呼出し方
View
<UserControl
x:Class="Hoge.Views.SampleView"
xmlns:converter="Hoge.Converters">
<UserControl.Resources>
<ResourceDictionary>
<converter:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Button
Content="サンプルボタン"
Visibility="{Binding IsButtonVisible, Converter={StaticResource BoolToVisibilityConverter}}" />
</Grid>
</UserControl>
ViewModel
ViewModelの以下のプロパティがConverterを通して、viewに適用されます。
public bool IsButtonVisible { get; set; }
2. ViewModelのbool値をViewのstring
に変換する
ViewModelのとあるプロパティのbool値がtrue
のときはふがふが
、false
のときはほげほげ
という文字列に変換するクラスです。
Converter
namespace Hoge.Converters
{
public class BoolToTextConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
try
{
if (value == null || (bool)value == false)
{
return "ほげほげ";
}
else
{
return "ふがふが";
}
}
catch (Exception)
{
// エラーのためログ出力
return "ぴよぴよ";
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
呼出し方
View
<UserControl
x:Class="Hoge.Views.SampleView"
xmlns:converter="Hoge.Converters">
<UserControl.Resources>
<ResourceDictionary>
<converter:BoolToTextConverter x:Key="BoolToTextConverter" />
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Button
Content="{Binding isHogeFugaPiyo, Converter={StaticResource BoolToTextConverter}}"
Visibility="Visible" />
</Grid>
</UserControl>
ViewModel
public bool isHogeFugaPiyo { get; set; }
3. ConverterParameter
の使用例
xaml側でConverterParameter
を使用して、Converterクラスのメソッドにパラメータを設定することもできます。下の例では、Convert
クラスの引数parameter
にinverse
の文字があると、Visibility
とCollapsed
が逆となるよう実装しています。
Converter
namespace Hoge.Converters
{
public class BoolToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
try
{
bool result;
if (value == null || (bool)value == false)
{
result = false;
}
else
{
result = true;
}
if (parameter?.ToString().ToLower() == "inverse")
{
return result ? Visibility.Collapsed : Visibility.Visible;
}
else
{
return result ? Visibility.Visible: Visibility.Collapsed;
}
}
catch (Exception)
{
// エラーのためログ出力
return Visibility.Collapsed;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
呼出し方
View
Visibility
にConverterParameter=inverse
を記載しています。
<UserControl
x:Class="Hoge.Views.SampleView"
xmlns:converter="Hoge.Converters">
<UserControl.Resources>
<ResourceDictionary>
<converter:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Button
Content="サンプルボタン"
Visibility="{Binding IsButtonVisible, Converter={StaticResource BoolToVisibilityConverter}, ConverterParameter=inverse}" />
</Grid>
</UserControl>
xamlでこのようにConverterParameter
を指定すると、ConvertBack
メソッドの引数parameter
にも同じようにConverterParameter
で指定した文字 (ここではinverse
) が入ってきます。
ViewModel
public bool IsButtonVisible { get; set; }
4. ConvertBack
の使用例
このサンプルではConvertBack
も実装しています。
Convert
メソッドでViewModel
のEmum値をstring
に変換して、ConvertBack
メソッドでViewのstringをViewModelのEnum値に変換しています。
ViewModelのSample
プロパティの値をConvert
メソッドを使用してViewの表示値に変換するのは今までのサンプルと同じ動きです。
今回はそれに加えて、ViewのTextBoxに値が入力されLostFocus
された際に、ConvertBackメソッドを通して、ViewModelのSample
プロパティに適切な値が入ります。
namespace Hoge.Converters
{
public class SampleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return "";
var sample = (SampleEnum)Enum.Parse(typeof(SampleEnum), value.ToString());
switch (sample)
{
case SampleEnum.Hoge:
return "ほげ";
case SampleEnum.Fuga:
return "ふが";
case SampleEnum.Piyo:
return "ぴよ";
default:
// エラー処理
return "";
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
string sampleText = (string)value;
switch (sampleText)
{
case "ほげ":
return SampleEnum.Hoge;
case "ふが":
return SampleEnum.Fuga;
case "ぴよ":
return SampleEnum.Piyo;
default:
// エラー処理
return null;
}
}
}
}
呼出し方
View
<UserControl
x:Class="Hoge.Views.SampleView"
xmlns:converter="Hoge.Converters">
<UserControl.Resources>
<ResourceDictionary>
<converter:SampleConverter x:Key="SampleConverter" />
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<TextBox Width="100" Text="{Binding Sample, Converter={StaticResource SampleConverter}" />
</Grid>
</UserControl>
ViewのTextBoxのLostFocus
時にConvertBackメソッドが走るのは、
TextBoxのUpdateSourceTriggerのデフォルト値がUpdateSourceTrigger=LostFocus
だからです。
例えばここで以下のようにUpdateSourceTrigger=PropertyChanged
を指定すると、テキストボックスに文字が入力されたり、一文字消去されるたびに、ViewModelのプロパティも変更されるので、そのたびにConvertBack
メソッドも走ります。
<TextBox Width="100" Text="{Binding Sample, Converter={StaticResource SampleConverter}, UpdateSourceTrigger=PropertyChanged}" />
ViewModel
public Class SampleClass
{
public enum SampleEnum
{
Hoge,
Fuga,
Piyo
}
public SampleEnum Sample { get; set; }
}
おわりに
Converterクラスは使い方によっては色々とバインディングの幅が広がりそうと感じました。