分享

.NET创建宿主设计器的总结(二)

 碧海山城 2010-01-05

通过查看DesignSurfaceView的代码:

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的父类DocumentDesignerGetView

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);

难道在调用dsBeginLoad以后,就有某种方式调用了DesignLoaderInitialize?并且,将服务加到了ds中?

查看designSurface.BeginLoad(loader);的代码:

internal void BeginLoad(DesignerLoader loader)

{

    this._loader = loader;

    try

    {

        this._loader.BeginLoad(this);

    }

    .......

}

我们可以发现关键的代码是他调用了DesignerLoader BeginLoad,并且把自己(DesignSurface)给传递进去,通过查看WorkflowDesignerLoader 父类BasicDesignerLoaderBeginLoad

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(设计器加载器)

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多