|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
有专家说:java不是跨平台,java就是平台,这很好的定义了java的特点。有了java,你只需要等待java平台在新平台上移植。这还不错吧!只是,java不是一个平台,而是多个平台。你需要在这个java平台移植到另一个java平台。创立|计划 Microsoft.NETFramework1.0供应了一个十分通用的计划时框架,可是没有供应任何完成代码来完成一个计划器,VisualStudio?.NET完成了一切的庞大逻辑,要第三方往从头完成这个庞大的逻辑。.NETFramework2.0引进了一组类可以用于计划器的完成。
了解.NETFramework怎样事情,十分主要的是要懂得计划器是怎样利用的。计划器是卖力办理计划界面上的组件的计划时代举动和体现的工具。框架联系关系计划时工具和运转时工具,为计划时组件供应了一个管道扩大运转时工具的举动。运转时,Form上的一个form和button这两个控件只是经由过程父子干系相干联,没有其他的工具来把持这些控件的性命周期。
Figure2
下面的图片看出计划时对照庞大,Form和button都有一个计划器相干联,两个工具都和Host容器相干联,host容器具有这两个工具,host容器也供应服务---比方拔取服务处置计划时的组件拔取,并跟踪所拔取的组件,UI服务用于显现对话,挪用匡助体系和计划情况相接洽。
Hostcontainer有很多职责,包含创立组件、绑定组件到计划器和为组件和计划器供应服务。从耐久化介质上加载组件和保留组件形态到耐久化介质。Hostcontainer供应打消、剪贴板功效和其他的服务等为完成鲁棒的计划器所依附的功效。
Figure3DesignerHosting hostcontainer利用designerloader耐久化计划器形态,designerloader利用序列化机制序列化组件。
服务扩大
The.NETFramework计划时框架是可扩大,供应的服务可用于完成形形色色的计划器。一个服务是供应工具可经由过程范例举行查询,典范的是你界说了服务的笼统类和接口和服务的完成。你能够从servicecontainer中增加大概删除服务。IDesignerHost是计划器次要的host接口,是一个ServiceContainer。服务是一个组件间能够共享的,正因云云,在创立和利用Service的时分必需遵守断定的划定规矩。
Services不被包管的,不管什么时候经由过程GetService办法哀求一个服务(Services),你必定要反省前往的是不是是一个无效工具。并非一切的服务在一切的平台上都是可用的,并且已经可用的服务将来不成能是可得。因而你的代码应该被写的下降文雅型,一般籍由必要某种服务而丧失某些特征,以防万逐一个服务也得不到。
假如你增加一个服务,记得在计划器的被disposed的时分移除它。计划器会时不时地创立和消毁,假如你没有往扫除一个服务的话,旧的计划器就会遗留在内存中。
<P> DesignSurface和DesignSurfaceManager
.NETFramework2.0引进了两个类DesignSurface和DesignSurfaceManager.给计划器供应宿主和给计划器供应服务。DesignSurface是利用者所感知的计划器,它是UI利用者利用改动计划时特性,DesignSurface大概被看成一个独自的计划者利用大概和DesignSurfaceManager分离利用为计划器使用程序供应多个DesignSurface。
DesignSurface供应好几个计划时服务,年夜多半服务都能够在服务容器中被掩盖,交换不成交换的服务长短法的,由于他们之间相互仰赖.注重增加到ServiceContaine完成了接口IDisposabler的服务当DesignSurface烧毁的时分城市被烧毁。
除供应缺省的服务,DesignSurface也供应了IDictionaryService,此服务供应一个利用联系关系键设置、检索和查找工具的复杂接口。不成能交换这些服务由于在每一个站点上没法交换这些服务。
DesignSurfaceManager是计划器的容器,它供应通用的服务以处置在计划者,属性窗口和其他的全局工具之间的事务路由.利用DesignSurfaceManager是可选择的,可是假如你想必要有一组计划者窗口,保举利用DesignSurfaceManager。
DesignSurfaceManager也供应了几个计划时服务(seeFigure5).。每个都能够在Protected属性ServiceContainer(服务容器)中被掩盖。和DesignSurface一样,DesignSurfaceManager一切的完成了接口IDisposabler的服务当计划器使用程序烧毁的时分城市被烧毁。
IDesignerEventService是一个出格地有效的服务.当一个计划器酿成活泼的时分,它同意一个计划器使用程序被关照到.IDesignerEventService供应了一组计划器和全局工具的会见点,比方属性窗口可以侦听到选择变更事务.
宿主form
为了树模一下宿主一个计划器是何等复杂,我写了上面的复杂代码来创立一个基础的Windows?Formsdesigner并显现它:
//CreatetheDesignSurfaceandloaditwithaform
DesignSurfaceds=newDesignSurface();
ds.BeginLoad(typeof(Form));
//GettheViewoftheDesignSurface,hostitinaform,andshowit
Controlc=ds.ViewasControl;
Formf=newForm();
c.Parent=f;
c.Dock=DockStyle.Fill;
f.Show();
在这一个代码片段中,我已用Form体例装载DesignSurface.一样地,你能用具有根计划器的任何组件装载DesignSurface.举例来讲,你能够改成装载UserControl或一个组件.
Figure6HostingWindowsFormsDesigner
供应下载的例子代码中有四种根组件:Form,UserControl,Component,andMyTopLevelComponent(一个图形计划器).当你运转例子的时分,一个ShellUI将会翻开.它包含一个工具箱,一个属性窗口,一个tabControl来宿主计划器,一个Outputwindow和一个SolutionExplorer,如所示..利用菜单的File|New|Form用窗口翻开一个新的WindowsFormsDesigner。这实质上就是利用下面所展现的代码加载一个计划器。与装载一个Form比拟较,例子中还展现了怎样装载UserControl大概组件。
创立一个根组件,也就是创立一个计划器完成IRootDesigner接口,然后指定这个组件的designer相干联,根组件的视图属性将出现给利用者。
DesignSurface供应的次要服务之一是IDesignerHost,IDesignerHost是用于供应计划器和对范例、服务和事件把持的次要接口。它也用于创立和烧毁组件。增加一个按钮到WindowsFormsdesigner所要做的事情就是从DesignSurface取得IDesignerHost接口并创立button,代码如
//AddaButtontotheForm
IDesignerHostidh=(IDesignerHost)ds.GetService(typeof(IDesignerHost));
Buttonb=(Button)idh.CreateComponent(typeof(Button));
//SettheParentofthisButtontotheRootComponent(theForm)
b.Parent=(Form)idh.RootComponent;
//UseComponentChangeServicetoannouncechangingofthe
//FormsControlscollection*/
IComponentChangeServiceicc=(IComponentChangeService)idh.GetService(typeof(IComponentChangeService));
icc.OnComponentChanging(idh.RootComponent,TypeDescriptor.GetProperties(idh.RootComponent)["Controls");
ItoolboxUser指定计划器撑持从Toolbox中增添控件到计划器,这意味着你的确必要一个完成ToolboxService的Toolbox,你可以用IToolboxUser接口把控件增加到根组件。比方:
/*AddaButtontotheFormusingIToolboxUser*/
IDesignerHostidh=(IDesignerHost)ds.GetService(typeof(IDesignerHost));
IToolboxUseritu=(IToolboxUser)idh.GetDesigner(idh.RootComponent);
itu.ToolPicked(newToolboxItem(typeof(Button)));
Figure8CustomRootDesignerUpdates
例子程序中双击Toolbox中的控件,控件被增加到自界说的根计划器,根计划器的视图中显现一个piechart如所示,点击GraphStyle链接改动视图到bargraph.
工具箱
MyRootDesigner完成IToolboxUser接口,这个接口有两个办法:GetToolSupportedandToolPicked.你能利用GetToolSupported过滤项目能被填加到计划器上的组件.进进ToolboxItem的CreateComponents办法(如名字使用,卖力制造组件)挪用的时分挪用ToolPicked。
既然我们已乐成增加控件和组件到计划器,让我们来看一下怎样完成一个Toolbox。起首,你的工具箱必要完成IToolboxService―这一个服务被增添到服务容器,任何必要利用的任何人都能够被存取。
同意项目从工具箱经由过程老鼠或键盘的增加到计划器上,示例程序的工具箱处置KeyDown和MouseDown事务。Enter键或鼠标双击事务,IToolboxUser.ToolPicked被挪用.示例展现了鼠标单击拖动控件怎样序列化ToolboxItem到DataObject和DoDragDrop办法挪用,鼠标mouseup事务IToolboxService.SerializeToolboxItem被挪用,并且项目将会被增添到计划器.
当一个控件大概组件被增加到计划器,你能藉由完成INameCreationService供应一个定制的名字给组件,示例程序展现了CreateName,ValidateName,andIsValidName的代码完成。
<P> MultipleDesignSurfaces
当办理多个DesignSurfaces,一个好主张是利用DesignSurfaceManager。它使得简单办理这些DesignSurfaces(注重DesignSurfaceManager的服务也是可得的到DesignSurface.)
挪用DesignSurfaceManager.CreateDesignSurface将挪用CreateDesignSurfaceCore,你可以重写这个函数往创立一个自界说的DesignSurface和增添服务。示例程序在类HostSurfaceManager经由过程重写这个函数创立了自界说的HostSurface:
protectedoverrideDesignSurfaceCreateDesignSurfaceCore(IServiceProviderparentProvider)
{
returnnewHostSurface(parentProvider);
}
你能经由过程HostSurfaceManager类的事务ActiveDesignSurfaceChanged更新output窗口,代码以下:
voidHostSurfaceManager_ActiveDesignSurfaceChanged(objectsender,ActiveDesignSurfaceChangedEventArgse)
{
ToolWindows.OutputWindowo=this.GetService(typeof(ToolWindows.OutputWindow))asToolWindows.OutputWindow;
o.RichTextBox.Text+="Newhostadded.
";
DesignerLoaders
到如今为止我已完成了DesignSurfaces、宿主计划器、增加控件、Toolbox和存取服务,像OutputWindow.下一个步骤要耐久化计划器。计划器载进程序好像你将会等候一样,卖力从耐久化介质加载Designerform.计划器载进程序只要少量的需求.现实上,你能创立WindowsFormsdesigner的一个实例。
除载进计划器,计划器载进程序对计划了局的保留也是计划器的职责。由于保留是可选择的举动,一个计划者载进程序侦听改动来自计划器的改动事务,并且主动的保留这些形态。.
.NETFramework2.0引进两个新的类来自界说加载器:BasicDesignerLoader和CodeDomDesignerLoader,示例使用举例申明二者的载进程序范例的完成。但是,假如你正在利用一个载进程序,它应当用来装载DesignSurface.你将利用的BeginLoad代码片段当利用载进程序的时分应当看起来有点像上面的代码:
//LoaditusingaLoader
ds.BeginLoad(newMyLoader());
DesignerLoader卖力载进DesignSurface的根组件并且创立任何组件.当制造一个新的Form或任何其他的根组件的时分,载进程序只是装载它.和从代码文件或一些其他的存储介质的载进,载进程序卖力剖析文件大概存储并且再创立根组件的任何其他的必须组件.
.NETFramework界说了一个笼统基类叫做DesignerLoader,用于加载和保留计划器到耐久介质。基类是abstract,因而任何耐久化模子都可使用这个类,可是,这也增添了完成类的庞大性。
BasicDesignerLoader供应了除任何数据的耐久格局外计划者载进程序的完整和一般的完成.像DesignerLoader,它是abstract,不处置关于耐久化格局的任何事变.BasicDesignerLoader处置尺度的事情:怎样时该保留,晓得该怎样再装载,并且追踪来自计划器的变更关照.它的特性包含对多依附加载,保留变更,并且延期加载撑持。
服务被BasicDesignerLoader增加到计划器的服务容器(servicecontainer)中。像其他的服务一样,你可以修正被回护的LoaderHost属性来修正可交换的服务。示例使用程序完成耐久化XML格局的类是BasicDesignerLoader.为了懂得它怎样事情,选择菜单File|Type|BasicDesignerLoader..然后选择菜单File|New|Form创立一个新的Form,检察它所天生的XML文件,选择菜单View|Code|XML.所看到的XML文件的内容相似于上面的内容:
<Objecttype="System.Windows.Forms.Form,System.Windows.Forms,
Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089"
name="Form1"children="Controls">
<Propertyname="Name">Form1</Property>
<Propertyname="DataBindings">
<Propertyname="DefaultDataSourceUpdateMode">OnValidation</Property>
</Property>
<Propertyname="ClientSize">292,273</Property>
</Object>
BasicDesignerLoader的PerformFlush和PerformLoad是二个abstract办法是你为完成序列化和反序列化的功效必需完成的办法.
CodeDomDesignerLoader
计划时序列化是经由过程发生代码来完成,代码天生Schema的一个应战是怎样处置多言语。.NETFramework被计划为多言语协同事情,因而我也但愿计划器可以天生多言语。有二个办法来到达办理这个成绩.第一要必要每一个言语厂商为他们的言语写代码天生引擎.不幸的是,没有言语厂商可以预期第三方组件厂商朝码天生的多样性需求.第二种体例要必要每一个组件厂商供应代码天生器给他们撑持的每种言语.由于被撑持的言语的数目是未知的,以是这相称糟。
为懂得决这个成绩,.NetFramework界说了一个工具模子叫做代码文档工具模子(CodeDOM),一切的原始代码能实质上分化为原始的元素的组合,并且CodeDOM是那些元素的工具模子.今世码依靠在CodeDOM,天生的工具模子可以给分歧言语的代码天生器天生得当的代码。
.NETFramework2.0引进了CodeDomDesignerLoader类,承继自BasicDesignerLoader。CodeDomDesignerLoader是一个经由过程CodeDom举行读写撑持的全功效的加载器。它是计划者加载器,因此你所必要做全体的是CodeDomProvider.
示例使用中你能够选择菜单File|Type|CodeDomDesigner-Loader来看CodeDom的实做例子。创立新的Form经由过程菜单File|New|Form---这创立一个DesignSurface和用CodeDomDesignerLoader加载它。检察代码,经由过程选择菜单View|Code|C#检察Form天生的C#代码,大概选择菜单View|Code|VB检察VisualBasic代码。
CompilerParameterscp=newCompilerParameters();
AssemblyName[]assemblyNames=Assembly.GetExecutingAssembly().GetReferencedAssemblies();foreach(AssemblyNameaninassemblyNames)
{
Assemblyassembly=Assembly.Load(an);
cp.ReferencedAssemblies.Add(assembly.Location);
}
cp.GenerateExecutable=true;
cp.OutputAssembly=executable;
cp.MainClass="DesignerHostSample."+
this.LoaderHost.RootComponent.Site.Name;
//CompileCodeCompileUnitusingCodeProvider
CSharpCodeProvidercc=newCSharpCodeProvider();
CompilerResultscr=cc.CompileAssemblyFromDom(cp,codeCompileUnit);
if(cr.Errors.HasErrors)
{
stringerrors=string.Empty;
foreach(CompilerErrorerrorincr.Errors)
{
errors+=error.ErrorText+"
";
}
MessageBox.Show(errors,"Errorsduringcompile.");
}
示例程序利用CSharpCodeProvider和VBCodeProvider天生代码,它也利用代码供应程序编译代码和运转可实行程序。
ITypeResolutionService是一个利用CodeDomDesignerLoader的时分的必需服务,卖力范例剖析。比方当从Toolbox增加一个控件到计划器的时分,这个服务被挪用剖析控件的范例。示例程序剖析程序集System.Windows.Forms的一切范例,以是你可以将Toolbox的WindowsForms下的控件增加到计划器
结论
你所看到的是,.NETFramework供应了一个壮大的和天真的计划器宿主基本布局。比上一个版本的VisualStudio计划器的可扩大性有助于计划着办理特别的需求或更多初级的场所.固然,计划者也能简单地宿主与VisualStudio表面。一样地.下载样例程序代码,你就可以够参按例子计划你本人的计划器。前几天同学问我学习方向的问题。有点想法,不知道对不对,怕误导同学,现在“开源一下”。注:括号内是我现在整理的时填加上的。 |
|