上一篇:
宿主工作流设计器(二)
接着说我们宿主工作流设计器的话题,本节我们讲讲定制一个工具箱,允许从其中拖放工作流活动到我们的设计器当中,以及上下文菜单的定制。
记得上一篇我们取得WorkFlowView的代码吗?有这么一段:
IDesignerHost designerHost = designSurface.GetService(typeof(IDesignerHost)) as IDesignerHost;
我们看看desingerHost,它其实是整个工作流组建中的服务容器,里面承载了各种工作流设计器所需的服务,上一篇说
DesignSurface也起到服务容器的作用,确切的说
DesignSurface是desingerHost的上级容器,我们如果了解微软的Container/Componenet/Service设计思想就应该知道,下级容器会向上级容器提供服务,而注册点应该是一致的,我们可以看看整个设计器的架构图就清楚了。
我们的工具箱拖放功能其实也是以服务的形式放到desingerHost中,而要使得工作流设计器支持这个功能,必须提供一个实现
IToolboxService接口的服务类,然后调用designerHost.AddService方法注册到designerHost中,当然这个类必须以组件(Component)形式存在,以便我们把它作为工具箱放到我们自己的UI中。
下面是MSDN文章中一个工作流工具箱的实现:

ToolboxService
namespace WorkflowDesignerControl


{
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;
using System.ComponentModel.Design;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Diagnostics;
using System.Drawing.Design;
using System.Drawing.Text;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Remoting;
using System.Runtime.Serialization.Formatters;
using System.Text;
using System.Windows.Forms.ComponentModel;
using System.Windows.Forms.Design;
using System.Windows.Forms;
using System;
using System.Workflow.Activities;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;


Class Toolbox#region Class Toolbox

/**//// <summary>
/// Class implementing the toolbox functionality in the sample.
/// Toolbox displays workflow components using which the workflow can be created
/// For more information on toolbox please refer to IToolboxService, ToolboxItem documentation
///
/// </summary>
[ToolboxItem(false)]
public class ToolboxService: Panel, IToolboxService

{
private const string CF_DESIGNER = "CF_WINOEDESIGNERCOMPONENTS";

private IServiceProvider provider;
private Hashtable customCreators;
private Type currentSelection;
private ListBox listBox = new ListBox();

//Create the toolbox and add the toolbox entries
public ToolboxService(IServiceProvider provider)

{
this.provider = provider;

Text = "Toolbox";
Size = new System.Drawing.Size(224, 350);

listBox.Dock = DockStyle.Fill;
listBox.IntegralHeight = false;
listBox.ItemHeight = 20;
listBox.DrawMode = DrawMode.OwnerDrawFixed;
listBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
listBox.BackColor = SystemColors.Window;
listBox.ForeColor = SystemColors.ControlText;
listBox.MouseMove +=new MouseEventHandler(OnListBoxMouseMove);
Controls.Add(listBox);

listBox.DrawItem += new DrawItemEventHandler(this.OnDrawItem);
listBox.KeyPress += new KeyPressEventHandler(this.OnListKeyPress);
listBox.SelectedIndexChanged += new EventHandler(this.OnListBoxClick);
listBox.DoubleClick += new EventHandler(this.OnListBoxDoubleClick);

AddToolboxEntries(listBox);
}

public void AddCreator(ToolboxItemCreatorCallback creator, string format)

{
AddCreator(creator, format, null);
}

public void AddCreator(ToolboxItemCreatorCallback creator, string format, IDesignerHost host)

{
if (creator == null || format == null)

{
throw new ArgumentNullException(creator == null ? "creator" : "format");
}

if (customCreators == null)

{
customCreators = new Hashtable();
}
else

{
string key = format;

if (host != null) key += ", " + host.GetHashCode().ToString();

if (customCreators.ContainsKey(key))

{
throw new Exception("There is already a creator registered for the format '" + format + "'.");
}
}

customCreators[format] = creator;
}

public void AddLinkedToolboxItem(ToolboxItem toolboxItem, IDesignerHost host)

{
}

public void AddLinkedToolboxItem(ToolboxItem toolboxItem, string category, IDesignerHost host)

{
}

public virtual void AddToolboxItem(ToolboxItem toolboxItem)

{
}

public virtual void AddToolboxItem(ToolboxItem toolboxItem, IDesignerHost host)

{
}

public virtual void AddToolboxItem(ToolboxItem toolboxItem, string category)

{
}

public virtual void AddToolboxItem(ToolboxItem toolboxItem, string category, IDesignerHost host)

{
}

public CategoryNameCollection CategoryNames

{
get

{

return new CategoryNameCollection(new string[]
{ "Workflow" });
}
}

public string SelectedCategory

{
get

{
return "Workflow";
}
set

{
}
}

private ToolboxItemCreatorCallback FindToolboxItemCreator(IDataObject dataObj, IDesignerHost host, out string foundFormat)

{
foundFormat = string.Empty;

ToolboxItemCreatorCallback creator = null;
if (customCreators != null)

{
IEnumerator keys = customCreators.Keys.GetEnumerator();
while (keys.MoveNext())

{
string key = (string)keys.Current;

string[] keyParts = key.Split(new char[]
{ ',' });
string format = keyParts[0];

if (dataObj.GetDataPresent(format))

{
// Check to see if the host matches.
if (keyParts.Length == 1 || (host != null && host.GetHashCode().ToString().Equals(keyParts[1])))

{
creator = (ToolboxItemCreatorCallback)customCreators[format];
foundFormat = format;
break;
}
}
}
}

return creator;
}

public virtual ToolboxItem GetSelectedToolboxItem()

{
ToolboxItem toolClass = null;
if (this.currentSelection != null)

{
try

{
toolClass = ToolboxService.GetToolboxItem(this.currentSelection);
}
catch (TypeLoadException)

{
}
}

return toolClass;
}

public virtual ToolboxItem GetSelectedToolboxItem(IDesignerHost host)

{
return GetSelectedToolboxItem();
}

public object SerializeToolboxItem(ToolboxItem toolboxItem)

{
DataObject dataObject = new DataObject();
dataObject.SetData(typeof(ToolboxItem), toolboxItem);
return dataObject;
}

public ToolboxItem DeserializeToolboxItem(object dataObject)

{
return DeserializeToolboxItem(dataObject, null);
}

public ToolboxItem DeserializeToolboxItem(object data, IDesignerHost host)

{
IDataObject dataObject = data as IDataObject;

if (dataObject == null)

{
return null;
}

ToolboxItem t = (ToolboxItem)dataObject.GetData(typeof(ToolboxItem));

if (t == null)

{
string format;
ToolboxItemCreatorCallback creator = FindToolboxItemCreator(dataObject, host, out format);

if (creator != null)

{
return creator(dataObject, format);
}
}

ret