.NET创建宿主设计器的总结(二)
来源:百度文库 编辑:神马文学网 时间:2024/10/01 08:45:41
通过查看DesignSurface的View的代码:
IComponent rootComponent = ((IDesignerHost) this._host).RootComponent;
........
IRootDesigner designer = ((IDesignerHost)
this._host).GetDesigner(rootComponent) as IRootDesigner;
.........
ViewTechnology[] supportedTechnologies =
designer.SupportedTechnologies;
int index = 0;
while (index < supportedTechnologies.Length)
{
ViewTechnology technology = supportedTechnologies[index];
return designer.GetView(technology);
}
(ViewTechnology 枚举 ,定义设计器宿主所支持的技术集的标识符。一般我们使用Default, 指定默认的视图技术支持就可以了。关于IComponent 可以参考下面的两篇文档)
1.
IComponent rootComponent = ((IDesignerHost) this._host).RootComponent;
我们可以看到,他先通过host(设计宿主)获得根组件,(比如我们设计一个顺序工作流,那么根组件就是一个SequentialActivity,如果设计一个Form,那么根组件就是一个Form)
2.
IRootDesigner designer = ((IDesignerHost)
this._host).GetDesigner(rootComponent) as IRootDesigner;
这里通过host(设计宿主)的GetDesigner方法,获得了根组件的根设计器(对比前面的例子,也就是一个SequentialWorkflowDesigner或者FormDocumentDesigner)
3.这里我们做个例子,一路追踪SequentialWorkflowDesigner,最后找到了它的基类,ActivityDesigner,实现了IRootDesigner 接口,查看他的GetView代码:
object IRootDesigner.GetView(ViewTechnology technology)
{
DesignSurface service = this.GetService(typeof(DesignSurface)) as DesignSurface;
IDesignerHost host = this.GetService(typeof(IDesignerHost)) as IDesignerHost;
if (((this.workflowView == null) && (service != null)) && ((host != null) && (host.RootComponent == this.Activity)))
{
this.workflowView = this.CreateView(technology);
}
return this.workflowView;
}
或者FormDocumentDesigner的父类DocumentDesigner的GetView:
object IRootDesigner.GetView(ViewTechnology technology)
{
if ((technology != ViewTechnology.Default) && (technology != ViewTechnology.WindowsForms))
{
throw new ArgumentException();
}
return this.frame;
}
我们可以发现,他们返回的是WorkflowView的实例或者DesignerFrame的实例,前者继承了UserControl,或者继承了Control,所以他们都能被添加到Panle子类的容器中。
关于Host:
我们可以发现他在DesignSurface构造的时候获得:
public DesignSurface() : this((IServiceProvider) null)
{
}
public DesignSurface(IServiceProvider parentProvider)
{
this._parentProvider = parentProvider;
this._serviceContainer = new
DesignSurfaceServiceContainer(this._parentProvider);
ServiceCreatorCallback callback = new
ServiceCreatorCallback(this.OnCreateService);
this.ServiceContainer.AddService(typeof(ISelectionService),
callback);
this.ServiceContainer.AddService(
typeof(IExtenderProviderService), callback);
this.ServiceContainer.AddService(
typeof(IExtenderListService), callback);
this.ServiceContainer.AddService(
typeof(ITypeDescriptorFilterService), callback);
this.ServiceContainer.AddService(
typeof(IReferenceService), callback);
this.ServiceContainer.AddService(typeof(DesignSurface), this);
this._host = new DesignerHost(this);
}
其他的战且不管,发现Host直接被new成了DesignerHost,他是IDesignerHost的默认实现。这个我们只能查看代码,也没有相关的文档,太难分析了。通过其他方法:
设计加载器
我们知道我们是可以自定义设计加载器的,通常在这里面我们会自己加一些服务,比如工具条,右键菜单等。代码如下:
internal sealed class WorkflowLoader : WorkflowDesignerLoader
{
#region Overrides from WorkflowDesignerLoader
protected override void Initialize()
{
base.Initialize();
// Add all the services to the loaderhost
IDesignerLoaderHost host = LoaderHost;
if (host != null)
{
this.SetBaseComponentClassName("foo.Workflow1");
host.AddService(typeof(IMenuCommandService), new
WorkflowMenuCommandService(host));
host.AddService(typeof(IToolboxService), new
ToolboxService(host));
}
}
}
我们前面刚刚说过,我们可以通过给设计面加服务来实现类似的操作,怎么这里有可以呢?而且,使用自定义设计器加载器的代码方式也很让人迷糊:
DesignSurface designSurface = new DesignSurface();
WorkflowLoader loader = new WorkflowLoader();
designSurface.BeginLoad(loader);
难道在调用ds的BeginLoad以后,就有某种方式调用了DesignLoader的Initialize?并且,将服务加到了ds中?
查看designSurface.BeginLoad(loader);的代码:
internal void BeginLoad(DesignerLoader loader)
{
this._loader = loader;
try
{
this._loader.BeginLoad(this);
}
.......
}
我们可以发现关键的代码是他调用了DesignerLoader 的BeginLoad,并且把自己(DesignSurface)给传递进去,通过查看WorkflowDesignerLoader 父类BasicDesignerLoader的BeginLoad:
public override void BeginLoad(IDesignerLoaderHost host)
{
if (this._host == null)
{
this._host = host;
..............
this.Initialize();
host.Activated += new EventHandler(this.OnDesignerActivate);
host.Deactivated += new EventHandler(this.OnDesignerDeactivate);
}
}
哈哈,关键的代码发现了,我们发现BeginLoad的参数正是IDesignerLoaderHost ,并且将传进来的DesignSurface赋给了它的一个实例变量,private IDesignerLoaderHost _host;
并且调用了Initialize()方法。
再回头看我们自定义加载器的Initialize()方法就很清楚了,我们获得了IDesignerLoaderHost (其实就是DesignSurface,并且将服务加给了DesignSurface)。
现在再来看一下IDesignerLoaderHost 的定义:提供一个接口,该接口可扩展设计器宿主以支持从序列化状态加载。
从字面的意思来说,IDesignerLoaderHost 是”设计器加载器的宿主“,搞不明白为什么他是DesignSurface??
1.我们的设计器宿主(DesignHost)被包含进了设计面(DesignSurace)中。可以通过设计器宿主的GetDesigner(设计的类型(Form/Button))方法获得设计器。
IDesigner designer =
((IDesignerHost) this._host).GetDesigner(rootComponent);
2.获得设计器以后就能通过设计器的GetView返回该设计器的视图显示。(就是我们可以看到的设计的样子)
3.可以通过设计宿主的designerHost.Container.Add(activity, rootSiteName);加入向我们的设计面中加入控件。
4.有时候也需要保存/加载设计器,所以就有了自定义的DesignLoader(设计器加载器)