2011年11月6日日曜日

InArgument(T) から String への変換

アクティビティを色々作成している中で、次のようなケースがありました。

  • デザイナ上で指定した画像のイメージをデザイナ上にプレビュー表示する

アクティビティのプロパティとしてファイル名を受け取るとして、そのファイル名で指定された画像をデザイナ上でプレビュー表示をする、というものです。その際にプロパティが String で指定されているのであればまだ簡単なのですが、アクティビティの場合ほとんどのプロパティは InArgument(T) を指定することもあり、値の変換には少し方法を変える必要があります。

例えばアクティビティ側のプロパティを以下のように記述しているとします。

   1: Public Property ImageFile As InArgument(Of String)

この場合、IValueConverter を利用して変換しようとした際に value 引数にわたってくるものは InArgument(Of String) となります。そのため単純に String に変換という方法は使えません。以下のようなロジックで変換する必要があります。

   1: 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
   2:     If Not TypeOf value Is ModelItem Then Return Nothing
   3:     Dim result As DrawingBrush = Nothing
   4:  
   5:     Dim inArgs = TryCast(DirectCast(value, ModelItem).GetCurrentValue, InArgument(Of String))
   6:     If inArgs Is Nothing Then Return Nothing
   7:  
   8:     Dim exp = inArgs.Expression
   9:     Dim vbexp = TryCast(exp, VisualBasicValue(Of String))
  10:     Dim lite = TryCast(exp, Literal(Of String))
  11:  
  12:     Dim impValue = ""
  13:     If lite IsNot Nothing Then
  14:         impValue = lite.Value
  15:     ElseIf vbexp IsNot Nothing Then
  16:         impValue = vbexp.ExpressionText
  17:     End If
  18:  
  19:     Dim target = IO.Path.GetFullPath(impValue)
  20:     If Not IO.File.Exists(target) Then Return Nothing
  21:  
  22:     Dim fileData As New BitmapImage()
  23:     fileData.BeginInit()
  24:     fileData.UriSource = New Uri(target)
  25:     fileData.EndInit()
  26:  
  27:     Return fileData
  28: End Function

注意点として実際にキャストを行う時に指定するのは InArgument ではなく ModelItem だという点と、その値としては Literal または VisualBasicValue の 2 パターンがあるという点です。その点さえ気を付ければ後は理解できるかと思います。

続いてこの IValueConverter の結果とバインディングする XAML 側の記述です。

   1: <Image Grid.Column="1" Grid.Row="0" 
   2:             Width="32" Height="32" Margin="4"
   3:             Source="{Binding ModelItem.ImageFile, Mode=OneWay, Converter={StaticResource ActivityImageConverter}}" />

あらかじめ XAML 上で IValueConverter を継承した変換クラスをリソースとして定義しておきます。上記の場合、ActivityImageConverter というクラスで実装していたのでそれをリソース定義しています。

   1: <sap:ActivityDesigner.Resources>
   2:     <wd:ActivityImageConverter x:Key="ActivityImageConverter" />

このように記述し、あとは Designer 属性での指定などを行うと以下のように挙動します。

inarg2image2

画像ファイルを指定すると、変換クラス側でファイル名よりイメージを取得、デザイナ上に反映できているのがわかると思います。変換クラス側で対象ファイルが存在しない場合は Null (Nothing) を返却していますので、存在しないファイルを指定した場合は次のようになります。

inarg2image3

このように変換クラスを用意する事でアクティビティに指定した値を元に文字列変換し、それをファイル名としてイメージを取得・表示できているのがわかると思います。

0 件のコメント:

コメントを投稿