【IT168 技术文档】如果你想建一个像PrePostSequence 那样的自定义活动,而使用者没有Visual Studio来使用它怎么办?此外,很多产品允许终端客户自定义工作流。为了解决这个问题,微软的新一代工作流提供了方便移植设计器的功能。在这个练习中,你可以看到移植设计器所需要的代码,并且体验下移植后的设计器。
1.打开解决方案
你可以使用练习9完成后的那个解决方案,经过一些操作,自己完成设计器移植。由于时间的限制,我们将直接打开设计器移植后的解决方案,看一下用来完成这些工作的代码。
(1)打开微软Visual Studio 2010.
(2)从以下路径打开解决方案: %TrainingKitInstallFolder%\Labs\ IntroToWF\Ex10-HostedDesigner\End.
(3)按CTRL+SHIFT+B来编译解决方案.
2.浏览HelloDesigner解决方案
HelloDesigner是一个WPF项目。
(1)展开HelloDesigner的被引用程序集。你可以看到为了移植设计器,这个项目主要引用了以下程序集:
? System.Activities.Presentation
·System.Activities.Core.Presentation
·System.Activities
·HelloWorkflow.Activities
·HelloWorkflow.Activities.Designers
(2)双击MainWindow.xaml文件,你可以看到用来描述移植设计器用户界面的WPF xaml代码。如以下的代码段所示。
(代码段 - Introduction to WF4 Lab – MainWindow XAML CSharp)
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="600" Width="1000">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="4*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Name="grid1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
</Grid>
<TextBox Grid.Row="1" Name="textXAML"
VerticalScrollBarVisibility="Visible" />
</Grid>
</Window>
(代码段 - Introduction to WF4 Lab – MainWindow XAML VB)
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="600" Width="1000">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="4*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Name="grid1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
</Grid>
<TextBox Grid.Row="1" Name="textXAML"
VerticalScrollBarVisibility="Visible" />
</Grid>
</Window>
(3)打开MainWindow.xaml.cs (C#) 或者MainWindow.xaml.vb,你可以看到用来实现移植设计器的源代码。
如下面所示, RegisterMetadata函数 使得设计器能够储存元数据。
(代码段- Introduction to WF4 Lab – RegisterMetadata method CSharp)
{
DesignerMetadata metaData = new DesignerMetadata();
metaData.Register();
AttributeTableBuilder builder = new AttributeTableBuilder();
MetadataStore.AddAttributeTable(builder.CreateTable());
}
(代码段- Introduction to WF4 Lab – RegisterMetadata method VB)
Dim metaData As DesignerMetadata = New DesignerMetadata()
metaData.Register()
Dim builder As AttributeTableBuilder = New AttributeTableBuilder()
MetadataStore.AddAttributeTable(builder.CreateTable())
End Sub
当你移植设计器,你可以控制工具栏。你可以选择出现在工具栏上的控件,该控件的分类,甚至控件的名称。如下面所示,CreateToolboxControl函数实现了上述功能。
(代码段- Introduction to WF4 Lab – CreateToolboxControl method CSharp)
{
//Create the ToolBoxControl
ToolboxControl ctrl = new ToolboxControl();
//Create a collection of category items
ToolboxCategory category = new ToolboxCategory("Hello Workflow");
//Creating toolboxItems
ToolboxItemWrapper tool0 = new ToolboxItemWrapper(
"System.Activities.Statements.Assign",
"System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
, null,
"Assign");
ToolboxItemWrapper tool1 = new ToolboxItemWrapper(
"System.Activities.Statements.Sequence",
"System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
null,
"Sequence");
ToolboxItemWrapper tool2 = new ToolboxItemWrapper(
"System.Activities.Statements.TryCatch",
"System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
null,
"Try It"); // Can use a different name
ToolboxItemWrapper tool3 = new ToolboxItemWrapper(
"HelloWorkflow.Activities.PrePostSequence",
"HelloWorkflow.Activities",
null,
"PrePostSequence");
//Adding the toolboxItems to the category.
category.Add(tool0);
category.Add(tool1);
category.Add(tool2);
category.Add(tool3);
//Adding the category to the ToolBox control.
ctrl.Categories.Add(category);
return ctrl;
}
(代码段- Introduction to WF4 Lab – CreateToolboxControl method VB)
'Create the ToolBoxControl
Dim ctrl As ToolboxControl = New ToolboxControl()
'Create a collection of category items
Dim category As ToolboxCategory = New ToolboxCategory("Hello Workflow")
'Creating toolboxItems
Dim tool0 As ToolboxItemWrapper = New ToolboxItemWrapper(
"System.Activities.Statements.Assign",
"System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
Nothing,
"Assign")
Dim tool1 As ToolboxItemWrapper = New ToolboxItemWrapper(
"System.Activities.Statements.Sequence",
"System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
Nothing,
"Sequence")
Dim tool2 As ToolboxItemWrapper = New ToolboxItemWrapper(
"System.Activities.Statements.TryCatch",
"System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
Nothing,
"Try It") ' Can use a different name
Dim tool3 As ToolboxItemWrapper = New ToolboxItemWrapper(
"HelloWorkflow.Activities.PrePostSequence",
"HelloWorkflow.Activities",
Nothing,
"PrePostSequence")
'Adding the toolboxItems to the category.
category.Add(tool0)
category.Add(tool1)
category.Add(tool2)
category.Add(tool3)
'Adding the category to the ToolBox control.
ctrl.Categories.Add(category)
Return ctrl
End Function
如下面所示,AddDesigner 函数把设计器加到你的窗口中。
(代码段- Introduction to WF4 Lab – AddDesigner method CSharp)
{
//Create an instance of WorkflowDesigner class
this.workflowDesigner = new WorkflowDesigner();
//Place the WorkflowDesigner in the middle column of the grid
Grid.SetColumn(this.workflowDesigner.View, 1);
// Flush the workflow when the model changes
workflowDesigner.ModelChanged += (s, e) =>
{
workflowDesigner.Flush();
textXAML.Text = workflowDesigner.Text;
};
//Load a new Sequence as default.
this.workflowDesigner.Load(new Sequence());
//Add the WorkflowDesigner to the grid
grid1.Children.Add(this.workflowDesigner.View);
// Add the Property Inspector
Grid.SetColumn(workflowDesigner.PropertyInspectorView, 2);
grid1.Children.Add(workflowDesigner.PropertyInspectorView);
// Add the toolbox
ToolboxControl tc = CreateToolboxControl();
Grid.SetColumn(tc, 0);
grid1.Children.Add(tc);
}
(代码段- Introduction to WF4 Lab – AddDesigner method VB)
'Create an instance of WorkflowDesigner class
workflowDesigner = New WorkflowDesigner()
'Place the WorkflowDesigner in the middle column of the grid
Grid.SetColumn(workflowDesigner.View, 1)
' Setup the Model Changed event handler
AddHandler workflowDesigner.ModelChanged,
Function(sender As Object, e As System.EventArgs)
' Flush the workflow when the model changes
workflowDesigner.Flush()
textXAML.Text = workflowDesigner.Text
Return Nothing
End Function
'Load a new Sequence as default.
workflowDesigner.Load(New Sequence())
'Add the WorkflowDesigner to the grid
grid1.Children.Add(workflowDesigner.View)
' Add the Property Inspector
Grid.SetColumn(workflowDesigner.PropertyInspectorView, 2)
grid1.Children.Add(workflowDesigner.PropertyInspectorView)
' Add the toolbox
Dim tc As ToolboxControl = CreateToolboxControl()
Grid.SetColumn(tc, 0)
grid1.Children.Add(tc)
End Sub
在构造函数中,以上的那些函数会被调用。
(代码段- Introduction to WF4 Lab – MainWindow method CSharp)
{
InitializeComponent();
RegisterMetadata();
AddDesigner();
}
(代码段- Introduction to WF4 Lab – MainWindow method VB)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
RegisterMetadata()
AddDesigner()
End Sub