2013年12月14日土曜日

WF における xaml について簡単な説明をしてみる

Workflow Foundation も xaml を利用しているので XAML Advent Calendar 2013 に参加してみました。他の方々に比べると異様な感じを醸し出しているのですが、まあ諦めてください。

まず Workflow Foundation での xaml ですが、2つの使われる場面があります。一つは、アクティビティデザイナーで利用するデザイナーの定義。もう一つはワークフロー自体の定義になります。

アクティビティデザイナーは WPF を利用しているので、WPF アプリケーションで利用している方法が全てそのまま利用可能です。

   1: <sap:ActivityDesigner x:Class="Speak1"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:s="clr-namespace:System;assembly=mscorlib"
   4:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   5:     xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"
   6:     xmlns:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation"
   7:     xmlns:sapc="clr-namespace:System.Activities.Presentation.Converters;assembly=System.Activities.Presentation">
   8:  
   9:     <sap:ActivityDesigner.Resources>
  10:         <sapc:ArgumentToExpressionConverter x:Key="ArgumentToExpressionConverter" />
  11:  
  12:         <DataTemplate x:Key="ExpandedActivityViewTemplate">
  13:             <Border BorderThickness ="1">
  14:                 <Grid >
  15:                     <Grid.ColumnDefinitions>
  16:                         <ColumnDefinition Width="Auto"/>
  17:                         <ColumnDefinition Width="*"/>
  18:                     </Grid.ColumnDefinitions>
  19:                     <Label Grid.Column="0" Grid.Row="1" Content="ワード" />
  20:                     <sapv:ExpressionTextBox Grid.Column="1" 
  21:                                             Width="200"
  22:                                             Expression="{Binding ModelItem.Text, Mode=TwoWay, 
  23:                                                                  Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=In}"
  24:                                             ExpressionType="s:String"
  25:                                             OwnerActivity="{Binding Path=ModelItem}"
  26:                                             UseLocationExpression="False" />
  27:                 </Grid>
  28:             </Border>
  29:         </DataTemplate>
  30:  
  31:         <DataTemplate x:Key="CollapsedActivityViewTemplate">
  32:             <Label Padding="0,0,0,0" FontStyle="Italic"
  33:                        Foreground="{x:Static SystemColors.GrayTextBrush}" HorizontalAlignment="Center"
  34:                        VerticalAlignment="Center" Content="ダブルクリックで展開します"></Label>
  35:         </DataTemplate>
  36:  
  37:         <Style x:Key="ConnectionSettingsStyle" TargetType="{x:Type ContentPresenter}">
  38:             <Setter Property="ContentTemplate" Value="{DynamicResource CollapsedActivityViewTemplate}" />
  39:             <Style.Triggers>
  40:                 <DataTrigger Binding="{Binding Path=ShowExpanded}" Value="true">
  41:                     <Setter Property="ContentTemplate" Value="{DynamicResource ExpandedActivityViewTemplate}" />
  42:                 </DataTrigger>
  43:             </Style.Triggers>
  44:         </Style>
  45:  
  46:     </sap:ActivityDesigner.Resources>
  47:  
  48:     <ContentPresenter Style="{DynamicResource ConnectionSettingsStyle}" Content="{Binding}" />
  49:  
  50: </sap:ActivityDesigner>

これはとある勉強会で利用したアクティビティデザイナーのソースです。WF 特有のコントロールを利用している箇所はありますが、それ以外の点では WPF アプリそのものというのが見てわかると思います。アクティビティデザイナーの特徴として Visual Studio やリホスティングデザイナー上で直接触れることができるのが、少々感覚的にも異なるところではないでしょうか。


なお上記のアクティビティをワークフローデザイナー上で見ると次のような感じになります。


image

もう一つの xaml を利用する箇所としてはワークフローになりますが、こちらは xaml と言っても完全に独自のものです。WPF で利用されている xaml とは形は同一でもその内容は別物となります。

   1: <Activity mc:Ignorable="sads sap" x:Class="Workflow1" sap:VirtualizedContainerService.HintSize="315,490" mva:VisualBasic.Settings="Assembly references and imported namespaces for internal implementation"
   2:  xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities"
   3:  xmlns:local="clr-namespace:NAWASAMI_ACIVITY"
   4:  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   5:  xmlns:mv="clr-namespace:Microsoft.VisualBasic;assembly=System"
   6:  xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities"
   7:  xmlns:s="clr-namespace:System;assembly=mscorlib"
   8:  xmlns:s1="clr-namespace:System;assembly=System"
   9:  xmlns:s2="clr-namespace:System;assembly=System.Xml"
  10:  xmlns:s3="clr-namespace:System;assembly=System.Core"
  11:  xmlns:s4="clr-namespace:System;assembly=System.ServiceModel"
  12:  xmlns:sa="clr-namespace:System.Activities;assembly=System.Activities"
  13:  xmlns:sad="clr-namespace:System.Activities.Debugger;assembly=System.Activities"
  14:  xmlns:sads="http://schemas.microsoft.com/netfx/2010/xaml/activities/debugger"
  15:  xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation"
  16:  xmlns:scg="clr-namespace:System.Collections.Generic;assembly=System"
  17:  xmlns:scg1="clr-namespace:System.Collections.Generic;assembly=System.ServiceModel"
  18:  xmlns:scg2="clr-namespace:System.Collections.Generic;assembly=System.Core"
  19:  xmlns:scg3="clr-namespace:System.Collections.Generic;assembly=mscorlib"
  20:  xmlns:sd="clr-namespace:System.Data;assembly=System.Data"
  21:  xmlns:sl="clr-namespace:System.Linq;assembly=System.Core"
  22:  xmlns:st="clr-namespace:System.Text;assembly=mscorlib"
  23:  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  24:   <Sequence sad:XamlDebuggerXmlReader.FileName="C:\Users\DemoUser\Desktop\NawaTech20131123\NAWASAMI_ACIVITY\NAWASAMI_ACIVITY\Workflow1.xaml" sap:VirtualizedContainerService.HintSize="275,450">
  25:     <Sequence.Variables>
  26:       <Variable x:TypeArguments="x:String" Name="tekitou" />
  27:     </Sequence.Variables>
  28:     <sap:WorkflowViewStateService.ViewState>
  29:       <scg3:Dictionary x:TypeArguments="x:String, x:Object">
  30:         <x:Boolean x:Key="IsExpanded">True</x:Boolean>
  31:       </scg3:Dictionary>
  32:     </sap:WorkflowViewStateService.ViewState>
  33:     <local:Speak1Activity Text="{x:Null}" DisplayName="魂のシャウト" sap:VirtualizedContainerService.HintSize="253,63" />
  34:     <Assign sap:VirtualizedContainerService.HintSize="253,60">
  35:       <Assign.To>
  36:         <OutArgument x:TypeArguments="x:String">[tekitou]</OutArgument>
  37:       </Assign.To>
  38:       <Assign.Value>
  39:         <InArgument x:TypeArguments="x:String">ムッシュがひどい</InArgument>
  40:       </Assign.Value>
  41:     </Assign>
  42:     <WriteLine sap:VirtualizedContainerService.HintSize="253,61" Text="[tekitou]" />
  43:     <Delay Duration="00:00:10" sap:VirtualizedContainerService.HintSize="253,22" />
  44:   </Sequence>
  45: </Activity>

この xaml をワークフローデザイナー上で見ると次のようなものになります。

image

シーケンシャル型のワークフローでは、処理の順番と xaml 上の記述が一致するのがわかると思います。ですので、ワークフローデザイナーがない環境であったとしても、xaml を直接編集して処理を入れ替えるとか行うのはまだ可能です。

それではもう一つのフローチャート型の場合を見てみます。

image

このワークフローの xaml は次のように記述されています。

   1: <Activity mc:Ignorable="sap sads" x:Class="FlowSample" sap:VirtualizedContainerService.HintSize="696,676" mva:VisualBasic.Settings="Assembly references and imported namespaces for internal implementation"
   2:  xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities"
   3:  xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   4:  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   5:  xmlns:mv="clr-namespace:Microsoft.VisualBasic;assembly=System"
   6:  xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities"
   7:  xmlns:s="clr-namespace:System;assembly=mscorlib"
   8:  xmlns:s1="clr-namespace:System;assembly=System"
   9:  xmlns:s2="clr-namespace:System;assembly=System.Xml"
  10:  xmlns:s3="clr-namespace:System;assembly=System.Core"
  11:  xmlns:sad="clr-namespace:System.Activities.Debugger;assembly=System.Activities"
  12:  xmlns:sads="http://schemas.microsoft.com/netfx/2010/xaml/activities/debugger"
  13:  xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation"
  14:  xmlns:scg="clr-namespace:System.Collections.Generic;assembly=System"
  15:  xmlns:scg1="clr-namespace:System.Collections.Generic;assembly=System.ServiceModel"
  16:  xmlns:scg2="clr-namespace:System.Collections.Generic;assembly=System.Core"
  17:  xmlns:scg3="clr-namespace:System.Collections.Generic;assembly=mscorlib"
  18:  xmlns:sd="clr-namespace:System.Data;assembly=System.Data"
  19:  xmlns:sl="clr-namespace:System.Linq;assembly=System.Core"
  20:  xmlns:st="clr-namespace:System.Text;assembly=mscorlib"
  21:  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  22:   <Flowchart sad:XamlDebuggerXmlReader.FileName="C:\Users\DemoUser\Desktop\NawaTech20131123\NAWASAMI_ACIVITY\NAWASAMI_ACIVITY\FlowSample.xaml" sap:VirtualizedContainerService.HintSize="656,636">
  23:     <sap:WorkflowViewStateService.ViewState>
  24:       <scg3:Dictionary x:TypeArguments="x:String, x:Object">
  25:         <x:Boolean x:Key="IsExpanded">False</x:Boolean>
  26:         <av:Point x:Key="ShapeLocation">270,2.5</av:Point>
  27:         <av:Size x:Key="ShapeSize">60,75</av:Size>
  28:         <av:PointCollection x:Key="ConnectorLocation">300,77.5 300,107.5 310,107.5 310,126.5</av:PointCollection>
  29:         <x:Double x:Key="Width">642</x:Double>
  30:       </scg3:Dictionary>
  31:     </sap:WorkflowViewStateService.ViewState>
  32:     <Flowchart.StartNode>
  33:       <x:Reference>__ReferenceID0</x:Reference>
  34:     </Flowchart.StartNode>
  35:     <FlowDecision x:Name="__ReferenceID0" sap:VirtualizedContainerService.HintSize="70,87">
  36:       <sap:WorkflowViewStateService.ViewState>
  37:         <scg3:Dictionary x:TypeArguments="x:String, x:Object">
  38:           <x:Boolean x:Key="IsExpanded">True</x:Boolean>
  39:           <av:Point x:Key="ShapeLocation">275,126.5</av:Point>
  40:           <av:Size x:Key="ShapeSize">70,87</av:Size>
  41:           <av:PointCollection x:Key="FalseConnector">345,170 375,170 375,243.5 345,243.5 345,360 368,360</av:PointCollection>
  42:           <av:PointCollection x:Key="TrueConnector">275,170 190,170 190,240</av:PointCollection>
  43:         </scg3:Dictionary>
  44:       </sap:WorkflowViewStateService.ViewState>
  45:       <FlowDecision.True>
  46:         <FlowStep x:Name="__ReferenceID2">
  47:           <sap:WorkflowViewStateService.ViewState>
  48:             <scg3:Dictionary x:TypeArguments="x:String, x:Object">
  49:               <av:Point x:Key="ShapeLocation">68,240</av:Point>
  50:               <av:Size x:Key="ShapeSize">244,60</av:Size>
  51:               <av:PointCollection x:Key="ConnectorLocation">190,300 190,330 52.5,330 52.5,96.5 292.5,96.5 292.5,126.5</av:PointCollection>
  52:             </scg3:Dictionary>
  53:           </sap:WorkflowViewStateService.ViewState>
  54:           <Assign sap:VirtualizedContainerService.HintSize="244,60">
  55:             <sap:WorkflowViewStateService.ViewState>
  56:               <scg3:Dictionary x:TypeArguments="x:String, x:Object">
  57:                 <x:Boolean x:Key="IsExpanded">True</x:Boolean>
  58:               </scg3:Dictionary>
  59:             </sap:WorkflowViewStateService.ViewState>
  60:           </Assign>
  61:           <FlowStep.Next>
  62:             <x:Reference>__ReferenceID0</x:Reference>
  63:           </FlowStep.Next>
  64:         </FlowStep>
  65:       </FlowDecision.True>
  66:       <FlowDecision.False>
  67:         <FlowStep x:Name="__ReferenceID1">
  68:           <sap:WorkflowViewStateService.ViewState>
  69:             <scg3:Dictionary x:TypeArguments="x:String, x:Object">
  70:               <av:Point x:Key="ShapeLocation">368,330</av:Point>
  71:               <av:Size x:Key="ShapeSize">244,60</av:Size>
  72:             </scg3:Dictionary>
  73:           </sap:WorkflowViewStateService.ViewState>
  74:           <Assign sap:VirtualizedContainerService.HintSize="244,60">
  75:             <sap:WorkflowViewStateService.ViewState>
  76:               <scg3:Dictionary x:TypeArguments="x:String, x:Object">
  77:                 <x:Boolean x:Key="IsExpanded">True</x:Boolean>
  78:               </scg3:Dictionary>
  79:             </sap:WorkflowViewStateService.ViewState>
  80:           </Assign>
  81:         </FlowStep>
  82:       </FlowDecision.False>
  83:     </FlowDecision>
  84:     <x:Reference>__ReferenceID1</x:Reference>
  85:     <x:Reference>__ReferenceID2</x:Reference>
  86:   </Flowchart>
  87: </Activity>

急に記載されている量が増えています。これはフローチャート型ワークフローの特徴である、アクティビティの自由な配置が関連しており、デザイナー上で好きに配置されたアクティビティの座標や、アクティビティ間を接続する線(フローノードと呼ばれるアクティビティ)の座標など、非常に多くの情報が必要になるためです。

また、処理の遷移を自由に行えるのもフローチャート型の特徴ですので、サンプルのように処理の遷移を戻した場合は「次に進むアクティビティ」を xaml 上の一つの要素として記述されることになり、シーケンシャルのように先頭から読み進めていくことが非常に難しくなっています。

このように Workflow Foundation でも xaml を利用していますが、アクティビティデザイナーのように WPF アプリケーションとして記述する部分と、ワークフローのように WF 独自の記述を行うもの二つが存在しています。xaml と言われると WPF などに言われるグラフィカルな世界をイメージされることが多いですが、WF のような処理を表す用途にも使われています。

ただ、WF3 で利用されていた xoml のように、気が付けば xaml じゃなくなる可能性はなきにしもあらずで・・・。

0 件のコメント:

コメントを投稿