元々の MSDN Blog では C# 版のソースだったので、ここでは VB 版です。
1: Public Class ToolboxIconExtraction
2:
3: Private Shared iconsDict As ResourceDictionary = Nothing
4:
5: Friend Overloads Shared Function ExtractIconResource(ByVal iconOrtypeName As String) As Object
6: If iconsDict Is Nothing Then
7: iconsDict = New ResourceDictionary With
8: {
9: .Source = New Uri("pack://application:,,,/System.Activities.Presentation;component/themes/icons.xaml")
10: }
11: End If
12:
13: Dim resourceKey = GetResourceName(iconOrtypeName)
14: Dim resource As Object = Nothing
15: If iconsDict.Contains(resourceKey) Then resource = iconsDict(resourceKey)
16: If Not TypeOf resource Is DrawingBrush Then resource = iconsDict("GenericLeafActivityIcon")
17:
18: Return resource
19: End Function
20:
21: Friend Overloads Shared Function ExtractIconResource(ByVal targetType As Type) As Object
22: Dim typeName = ""
23: If targetType.IsGenericType Then
24: typeName = targetType.GetGenericTypeDefinition.Name
25: Else
26: typeName = targetType.Name
27: End If
28: Return ExtractIconResource(typeName)
29: End Function
30:
31: Friend Overloads Shared Function GetResourceName(ByVal typeName As String) As String
32: Dim resourceKey = typeName
33: resourceKey = resourceKey.Split(".").Last
34: resourceKey = resourceKey.Split("`").First
35:
36: If resourceKey = "Flowchart" Then
37: resourceKey = "FlowChart"
38: End If
39: If Not resourceKey.EndsWith("Icon") Then
40: resourceKey += "Icon"
41: End If
42: Return resourceKey
43: End Function
44:
45: End Class
まずはアイコン抽出用のクラスを記述します。ポイントは
pack://application:,,,/System.Activities.Presentation;component/themes/icons.xaml
にて提供されているリソースを利用するところです。今までの方法では、Microsoft.VisualStudio.Activities.dll を利用していたりと、権利上問題のある手法でしたが、これは .NET 標準の Dll ですので PC にインストールされているものを利用できます。
1: Public Class ToolboxItemConverter
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 Not TypeOf value Is String Then Return Nothing
6: Dim result As DrawingBrush = Nothing
7: result = TryCast(ToolboxIconExtraction.ExtractIconResource(value.ToString), DrawingBrush)
8: Return result
9: End Function
10:
11: 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
12: Throw New NotImplementedException
13: End Function
14:
15: End Class
続いては XAML 上に指定する Converter クラスを作成します。このクラスは XAML 上で Toolitem を作成する段階で呼び出され、リソースに格納されているアイコンを抽出、返却します。上記コードでは ToolboxItem の表示名(DisplayName プロパティ)の値からリソースを抽出していますが、そのあたりを変更すれば Type から取得する事も簡単です。Convert メソッドのロジックをちょっと変更すれば済みます。
1: <sapt:ToolboxControl x:Name="toolbox">
2: <sapt:ToolboxControl.Style>
3: <Style TargetType="{x:Type sapt:ToolboxControl}">
4: <Style.Resources>
5: <local:ToolboxItemConverter x:Key="IconConverter"/>
6: <DataTemplate x:Key="IconTemplate">
7: <Rectangle Width="18" Height="18" Fill="{Binding}"/>
8: </DataTemplate>
9: <DataTemplate x:Key="ToolTemplate" DataType="{x:Type sapt:ToolboxItemWrapper}">
10: <Grid>
11: <Grid.ColumnDefinitions>
12: <ColumnDefinition Width="Auto"/>
13: <ColumnDefinition Width="*" SharedSizeGroup="toolLabel"/>
14: </Grid.ColumnDefinitions>
15: <ContentControl Grid.Column="0"
16: Content="{Binding Path=DisplayName, Converter={StaticResource IconConverter}}"
17: ContentTemplate="{StaticResource IconTemplate}"/>
18: <TextBlock Grid.Column="1" Text="{Binding Path=DisplayName}" Margin="5,1,5,0"/>
19: </Grid>
20: </DataTemplate>
21: </Style.Resources>
22: <Setter Property="ToolTemplate" Value="{StaticResource ToolTemplate}" />
23: </Style>
24: </sapt:ToolboxControl.Style>
25: </sapt:ToolboxControl>
そして XAML 側に記載している TooboxControl を貼り付けている部分を上記のように変更します。この際、local:ToolboxItemConverter の箇所でエラーが出る事がありますが、その際には
xmlns:wd="clr-namespace:Workflow4Designer"
のような形で名前空間を追加し、wd:ToolboxItemConverter ~ として記述してください。
これで「ほとんど」の作業が終了です。特殊なケースにあたる Flowchart 関係の指定も上記ロジックには含まれています……が、もう一つだけ特殊ケースがあります。
TransactedReceiveScope アクティビティがその特殊ケースで、こいつのアイコン名は TransactionReceiveScopeIcon です。Transacted~ではなくTransaction~というミスタイプ感満載ですが、ここはハードコーディングで対応してしまって構わないと思います。
これでアイコン周りは大分スッキリです。恐らく追加されたアクティビティに対しては、リソースを追加していってあげれば大丈夫なんじゃないかな、と(試していません)。
0 件のコメント:
コメントを投稿