2011年11月2日水曜日

MessageBoxIcon の値を IValueConverter で変換

メッセージボックスを表示するアクティビティを作っていて、デザイナ上でアイコンやボタンの設定をラジオボタンにて選択させようとした時、MessageBoxIcon 列挙値を変換するような IValueConverter を用意してあげれば、ラジオボタンにバインドができて非常に楽になります。ただし、その際に少しだけ注意する点がありました。

Twitter で @shibayan 先生に教えてもらったのですが、MessageBoxIcon とかを ToString すると、一部の値(Information とか Errorとか)は内部で別の値(Asterisk や Hand)に変換されてしまいます。これが理由かどうかは分かりませんが、ToString で文字変換を行うのは非推奨な手段ということです。

そのあたりを踏まえてこんなロジックで IValueConverter を実装してみました。

   1: Public Class EnumBooleanConverter
   2:     Implements IValueConverter
   3:  
   4:     Public Function Convert(value As Object, targetType As System.Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
   5:         If (value Is Nothing) OrElse (parameter Is Nothing) Then Return False
   6:  
   7:         If Not [Enum].IsDefined(value.GetType, value) Then Return False
   8:  
   9:         Dim inputValue = [Enum].Parse(value.GetType, parameter.ToString)
  10:         Return (inputValue = value)
  11:     End Function
  12:  
  13:     Public Function ConvertBack(value As Object, targetType As System.Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
  14:         If (value Is Nothing) OrElse (parameter Is Nothing) Then Return Nothing
  15:  
  16:         Dim useValue = CType(value, Boolean)
  17:         Dim targetValue = parameter.ToString
  18:         If useValue Then Return [Enum].Parse(targetType, targetValue)
  19:         Return Nothing
  20:     End Function
  21:  
  22: End Class

こんな感じで用意してあげる事で、アクティビティデザイナーや WPF でラジオボタンにバインドを行う事ができます。

   1: <RadioButton Content="情報" GroupName="grpIcon" 
   2:                 IsChecked="{Binding Path=ModelItem.Icon, Mode=TwoWay, 
   3:                 Converter ={StaticResource EnumBooleanConverter},
   4:                 ConverterParameter =Information}"  />
   5: <RadioButton Content="問合せ" GroupName="grpIcon" 
   6:                 IsChecked="{Binding Path=ModelItem.Icon, Mode=TwoWay, 
   7:                 Converter ={StaticResource EnumBooleanConverter},
   8:                 ConverterParameter =Question}"  />

こんな感じでバインドします。ConvertParameter にて実際の列挙値を示す「文字列」を設定し、IValueConverter 内部でその値を変換する感じです。ただし WPF であればここまででいいのですが、WF のアクティビティデザイナーで利用する場合、上記のバインドは InArgument 等のプロパティにはそのままだと利用できません。Convert メソッドが呼ばれた際の targetType が InArgument となってしまうので、もう一段階の変換が必要になります。

それが面倒な場合、または InArgument を利用する必要がない場合は普通に Property を利用すれば直接バインドできます。

0 件のコメント:

コメントを投稿