The .NET Framework設計時框架是可擴展,提供的服務可用于實現各式各樣的設計器。一個服務是提供對象可通過類型進行查詢,典型的是你定義了服務的抽象類和接口和服務的實現。你可以從service container中添加或者刪除服務。IDesignerHost是設計器主要的host接口,是一個Service Container。服務是一個組件間可以共享的,正因如此,在創建和使用Service的時候必須遵循確定的規則。
為了示范一下宿主一個設計器是多么簡單,我寫了下面的簡單代碼來創建一個基本的Windows? Forms designer并顯示它:
// Create the DesignSurface and load it with a form
DesignSurface ds = new DesignSurface(); ds.BeginLoad(typeof(Form));
// Get the View of the DesignSurface, host it in a form, and show it
Control c = ds.View as Control; Form f = new Form(); c.Parent = f; c.Dock = DockStyle.Fill; f.Show(); 在這一個代碼片斷中,我已經用Form方式裝載 DesignSurface. 同樣地,你能用擁有根設計器的任何組件裝載 DesignSurface. 舉例來說,你可以改為裝載 UserControl 或一個組件.
Figure 6 Hosting Windows Forms Designer
提供下載的例子代碼中有四種根組件:Form, UserControl, Component, and MyTopLevelComponent (一個圖形設計器). 當你運行例子的時候,一個Shell UI 將會打開. 它包括一個工具箱,一個屬性窗口, 一個tab Control來宿主設計器,一個Output window和一個Solution EXPlorer,如圖6所示..使用菜單的File New Form 用窗口打開一個新的Windows Forms Designer。這本質上就是使用上面所展示的代碼加載一個設計器。與裝載一個Form相比較,例子中還展示了如何裝載UserControl或者組件。
DesignSurface 提供的主要服務之一是 IDesignerHost,IDesignerHost是用于提供設計器和對類型、服務和事務控制的主要接口。它也用于創建和銷毀組件。添加一個按鈕到Windows Forms designer所要做的工作就是從DesignSurface獲得IDesignerHost接口并創建button,代碼如圖7
// Add a Button to the Form IDesignerHost idh = (IDesignerHost)ds.GetService(typeof(IDesignerHost)); Button b = (Button)idh.CreateComponent(typeof(Button)); // Set the Parent of this Button to the RootComponent (the Form) b.Parent = (Form)idh.RootComponent; // Use ComponentChangeService to announce changing of the // Form's Controls collection */ IComponentChangeService icc = (IComponentChangeService) idh.GetService(typeof(IComponentChangeService)); icc.OnComponentChanging(idh.RootComponent, TypeDescr ItoolboxUser指定設計器支持從Toolbox中增加控件到設計器,這意味著你確實需要一個實現ToolboxService的Toolbox,你能夠用IToolboxUser接口把控件添加到根組件。例如:
/* Add a Button to the Form using IToolboxUser */
IDesignerHost idh = (IDesignerHost)ds.GetService(typeof(IDesignerHost)); IToolboxUser itu = (IToolboxUser)idh.GetDesigner(idh.RootComponent); itu.ToolPicked(new ToolboxItem(typeof(Button)));
// Load it using a Loader ds.BeginLoad(new MyLoader()); DesignerLoader 負責載入 DesignSurface 的根組件而且創建任何組件. 當創造一個新的Form或任何其他的根組件的時候,載入程序只是裝載它. 和從代碼文件或一些其他的存儲介質的載入,載入程序負責解析文件或者存儲而且再創建根組件的任何其他的必需組件.
示例應用中你可以選擇菜單File Type CodeDomDesigner-Loader來看CodeDom的實做例子。創建新的Form通過菜單File New Form---這創建一個DesignSurface和用CodeDomDesignerLoader加載它。查看代碼,通過選擇菜單View Code C#查看Form生成的C#代碼,或者選擇菜單View Code VB查看Visual Basic代碼。
CompilerParameters cp = new CompilerParameters();
AssemblyName[] assemblyNames = Assembly.GetExecutingAssembly().GetReferencedAssemblies(); foreach (AssemblyName an in assemblyNames) { Assembly assembly = Assembly.Load(an); cp.ReferencedAssemblies.Add(assembly.Location); }cp.GenerateExecutable = true; cp.OutputAssembly = executable;cp.MainClass = "DesignerHostSample." + this.LoaderHost.RootComponent.Site.Name;// Compile CodeCompileUnit using CodeProvider CSharpCodeProvider cc = new CSharpCodeProvider(); CompilerResults cr = cc.CompileAssemblyFromDom(cp, codeCompileUnit);if (cr.Errors.HasErrors) { string errors = string.Empty; foreach (CompilerError error in cr.Errors) { errors += error.ErrorText + "/n"; } MessageBox.Show(errors, "Errors during compile."); }