上一篇:宿主工作流设计器(一)
接着上一篇文章说,前面已经定义了一个WorkflowLoader类来完成工作流的导入与导出,下面我们接着完成工作流设计器的工作。
本章我们主要讲述使用WorkflowView这个类在UI上呈现出一个工作流设计器。
首先我们创建DesignSurface的一个实例:
DesignSurface designSurface = new DesignSurface();
前面已经讲过这个类是负责完成UI呈现工作的,这个类起到一个服务容器的作用,采用了微软经典的Service/Component模型,里面装载UI呈现设计器所需的各种服务,我们可以从其中取得一个设计器宿主对象,它是一个IDesignerHost接口,然后从这个宿主中获取到宿主在其中的工作流设计器,关于设计器设计器宿主结构可以参看MSDN。
WorkflowLoader loader = new WorkflowLoader();
loader.Xoml = xomlFile;
designSurface.BeginLoad(loader);
IDesignerHost designerHost = designSurface.GetService(typeof(IDesignerHost)) as IDesignerHost;
IRootDesigner rootDesigner = designerHost.GetDesigner(designerHost.RootComponent) as IRootDesigner;
IRootDesigner接口为我们提供了一个GetView方法,通过调用该方法我们就得到了一个WorkFlowView对象,而这个对象是一个Control,我们把这个Control放到我们程序的UI中,这样,一个工作流设计器就被我们宿主出来了,而当前工作流设计器所呈现的工作流就是上面代码中xomlFile(一个String类型变量,存储一个工作流文件路径)所定义的工作流。前面一篇文章已经讲述了WorkflowLoader类如何导入导出这个Xoml文件,这里就不再熬述。loader.Xoml = xomlFile;
designSurface.BeginLoad(loader);
IDesignerHost designerHost = designSurface.GetService(typeof(IDesignerHost)) as IDesignerHost;
IRootDesigner rootDesigner = designerHost.GetDesigner(designerHost.RootComponent) as IRootDesigner;
前面文章说过,我们的设计器是面向客户的,而VS中的设计器顶部标题是“顺序工作流”,“状态机工作流“之类的专业字眼,因此我们必须让它变成我们定义的文字,刚开始我一直觉得这个标题应该是存在于WorkflowView的Title之类的属性中,然而仔细研究后发现问题并不是这么简单,微软的设计比我想象的要灵活得多,先汗一个!
设计器标题并不由设计器对象所决定,而是由载入到WorkflowView中的WorkFlow决定,Framework中所有的Activity对象都可以应用DesignerAttribute特性(SequentialWorkflowActivity也是继承了Activity),我们都知道Control类也可以用这个特性影响控件的设计时外观,而WorkFlow设计器也这样做了,我们可以定义个设计类来定制WorkFlow的设计时外观,我们看看一个DesignerAttribute构造函数的定义:
public DesignerAttribute(Type designerType, Type designerBaseType);
第一个参数是设计类的类型,第二个函数的设计类的基类型。通过MSDN可以知道,工作流对象的设计时基类是IRootDesigner,而对于工作流我们可以用继承自SequentialWorkflowRootDesigner的类来构造我们的设计类,而对于活动我们可以继承自ActivityDesigner。当然SequentialWorkflowRootDesigner也继承自ActivityDesigner,之所以用SequentialWorkflowRootDesigner是为了让我们针对工作流获得更多的可定义项。我们继承SequentialWorkflowRootDesigner后重写Header属性就可以改变工作流设计器标题,ActivityDesigner类中还有很多属性可以让我们自定义设计时外观,例如我们想在可以拖入工作流的地方写上帮助提示可以重写HelpText属性,相应的,我们前面提到我们希望当按钮点击工作流开始箭头图标时候必须屏蔽掉 View SequentialWorkflow, View Cancel Handler和View Fault Handlers这三个菜单,我们可以重写ShowSmartTag属性,让它总是返回false就可以做到,我们还可以重写Initialize方法在活动载入时执行一些操作或定制一些行为。下面是一个设计类示例:public class CustomSequentialWorkflowDesigner : SequentialWorkflowRootDesigner
{
private string m_text = null;
protected override SequentialWorkflowHeaderFooter Header
{
get
{
base.Header.Text = "我的工作流";
return base.Header;
}
}
protected override void Initialize(System.Workflow.ComponentModel.Activity activity)
{
this.HelpText = "从工具箱中拖放活动到此处";
}
protected override bool ShowSmartTag
{
get
{
return false;
}
}
}
{
private string m_text = null;
protected override SequentialWorkflowHeaderFooter Header
{
get
{
base.Header.Text = "我的工作流";
return base.Header;
}
}
protected override void Initialize(System.Workflow.ComponentModel.Activity activity)
{
this.HelpText = "从工具箱中拖放活动到此处";
}
protected override bool ShowSmartTag
{
get
{
return false;
}
}
}
读到这里相信大家已经托管出一个属于自己的工作流设计器了,后面我们接着说说工具箱的定义和其他一些相关内容。