RadioButtonは複数の選択肢から1つを選ぶ時によく使われるコントロール。
ただし、RadioButtonにチェックマークを付ける為のIsCheckedプロパティはbooleanなので、3つ以上の選択肢から選ばせる場合など作り込みが必要になる。
列挙型の値をRadioButtonにバインドさせる方法を考える。
WPFのBindingの仕組みでは、間にコンバータを挟んで値を変換しながらバインドする事が出来る。
以下の例では、特定の列挙型に依存しない汎用的なコンバータを作成し、複数のRadioButtonを1つのデータへバインドさせている。
列挙型をBooleanへ変換するコンバータ
public class EnumToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var parameterString = parameter as string;
if (null == parameterString)
return DependencyProperty.UnsetValue;
if (!Enum.IsDefined(value.GetType(), value))
return DependencyProperty.UnsetValue;
var parameterValue = Enum.Parse(value.GetType(), parameterString);
return parameterValue.Equals(value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
var parameterString = parameter as string;
if (null == parameterString)
return DependencyProperty.UnsetValue;
if (true.Equals(value))
return Enum.Parse(targetType, parameterString);
else
return DependencyProperty.UnsetValue;
}
}
IValueComverterインターフェースを実装したクラスの作成 (1行目)
IValueConverterインターフェースを実装する事で、バインディンク時のコンバータとして利用できるクラスを作成する事が出来る。
enumからbooleanへの変換 (3~14行目)
Convertメソッドにenumからbooleanへ変換するコードを書く。
意図しない値が入ってきた時はDependencyProperty.UnsetValueを戻り値にする。
パラメータparampeterはXAMLから渡される値で、列挙型の値を文字列で指定させる仕様。
Enum.Parseメソッドを使って文字列からenumを作成して、等しいかどうかを戻り値にする。
こうする事で、特定の列挙型に依存しない汎用的なコンバータになる。
booleanからenumへの変換 (16~26行目)
ConvertBackメソッドにbooleanからenumへ変換するコードを書く。
パラメータparampeterはXAMLから渡される値で、列挙型の値を文字列で指定させる仕様。
trueの時は、parameterの文字列からenumを作成してそれを戻り値にする。
falseの時は、DependencyProperty.UnsetValueを戻り値にする。
XAML
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="150" Width="250">
<Window.Resources>
<ResourceDictionary>
<local:EnumToBooleanConverter x:Key="EnumToBoolean"/>
</ResourceDictionary>
</Window.Resources>
<StackPanel Margin="20">
<RadioButton Content="タイプ1" IsChecked="{Binding Path=Sample,Mode=TwoWay,Converter={StaticResource EnumToBoolean},ConverterParameter=TYPE1,UpdateSourceTrigger=PropertyChanged}"/>
<RadioButton Content="タイプ2" IsChecked="{Binding Path=Sample,Mode=TwoWay,Converter={StaticResource EnumToBoolean},ConverterParameter=TYPE2,UpdateSourceTrigger=PropertyChanged}"/>
<RadioButton Content="タイプ3" IsChecked="{Binding Path=Sample,Mode=TwoWay,Converter={StaticResource EnumToBoolean},ConverterParameter=TYPE3,UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</Window>
Resourcesへコンバータを定義 (9~13行目)
上記で作成したコンバータを利用できるようにWindow.Resourcesへ定義する。
定義したコンバータにはx:Key属性を使って名前をつけている。
RadioButtonのバインド (15~16行目)
3つのRadioButtonは全てSampleという同じ値へバインドさせている。
Converterに作成したコンバータを定義する。
ConverterParameterはコンバータのparameterへ渡される値なので、RadioButtonにチェックが付く時の列挙型の値を指定する。
更に、プロパティが更新されたら表示が更新されるようにUpdateSourceTriggerにはPropertyChangedを指定している。
ソース
public enum SampleType
{
TYPE1,
TYPE2,
TYPE3
};
public class SampleData : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string name)
{
if (null == this.PropertyChanged) return;
this.PropertyChanged(this, new PropertyChangedEventArgs(name));
}
private SampleType _Sample;
public SampleType Sample
{
get { return _Sample; }
set { _Sample = value; OnPropertyChanged("Sample"); }
}
}
public partial class MainWindow : Window
{
private SampleData Data;
public MainWindow()
{
Data = new SampleData();
Data.Sample = SampleType.TYPE1;
this.DataContext = Data;
InitializeComponent();
}
}
列挙型を定義 (1~6行目)
サンプルとして3つの値を定義した。
バインドされるデータの定義 (12~28行目)
コントロールとデータの双方向で更新されるように、INotifyPropertyChangedインターフェースを実装したデータ構造を作成する。

コメント
コメントを投稿