System.ComponentModel.Design.DesignSurface是為設(shè)計(jì)組件提供一個(gè)用戶界面,通過它可以實(shí)現(xiàn)一個(gè)簡單的窗體設(shè)計(jì)器。
在構(gòu)建之前,我們需要引入System.Design.dll,否則會(huì)出現(xiàn)找不到DesignSurface的錯(cuò)誤。
1 private void Form1_Load(object sender, EventArgs e) 2 { 3 //引用System.Deisgn.dll 4 DesignSurface ds = new DesignSurface(); 5 //開始加載窗體 6 ds.BeginLoad(typeof(Form)); 7 Control designerContorl = (Control)ds.View; 8 designerContorl.Dock = DockStyle.Fill; 9 this.Controls.Add(designerContorl);10 }
運(yùn)行后出現(xiàn)簡單的一個(gè)UI設(shè)計(jì)器
但是該設(shè)計(jì)器并不能實(shí)現(xiàn)控件拖放和UI設(shè)計(jì)器,以及控件的屬性配置。
為了支持從源代碼加載初始化窗體,需要對源碼中的相關(guān)方法進(jìn)行解析,這里我們 CodeDomDesignerLoader來實(shí)現(xiàn)定制化業(yè)務(wù),CodeDomDesignerLoader是提供用于實(shí)現(xiàn)基于 CodeDOM 的設(shè)計(jì)器加載程序的基類。
繼承它的類需要重寫CodeCompileUnit Parse()方法,來實(shí)現(xiàn)加載窗體:
1 protected override CodeCompileUnit Parse() 2 { 3 4 #region 源文件讀取 5 var sw = new StreamReader(@"E:\FrmUser.cs"); 6 var sw_designer = new StreamReader(@"E:\FrmUser.Designer.cs"); 7 8 string formCodeCS = sw.ReadToEnd(); 9 string formCodeDesigner = sw_designer.ReadToEnd();10 11 List<string> source = new List<string>();12 source.Add(formCodeCS);13 source.Add(formCodeDesigner);14 15 #endregion16 //Rolsyn解析C#17 var rootDesigner = Source2CodeDom.Parse(formCodeDesigner);18 codeDesingerCompileUnit = Source2CodeDom.GetDesignerCodeComplieUnit(rootDesigner);19 var rootCS = Source2CodeDom.Parse(formCodeCS);20 codeCSCompileUnit = Source2CodeDom.GetCodeComplieUnit(rootCS);21 //MergeFormSource22 string mergeS = Source2CodeDom.MergeFormSource(formCodeDesigner, formCodeCS);23 codeMergeCompileUnit = Source2CodeDom.GetMergeDesignerCodeComplieUnit(mergeS);24 return codeMergeCompileUnit;
解析的方法如下,但是此解析只是用于代碼的生成,并不能用戶UI界面的顯示:
1 public static CodeCompileUnit GetDesignerCodeComplieUnit2(CompilationUnitSyntax root) 2 { 3 CodeCompileUnit ccu = new CodeCompileUnit(); 4 var firstMember = root.Members[0]; 5 var namespaceDeclration = (NamespaceDeclarationSyntax)firstMember; 6 var designClassDeclaration = (ClassDeclarationSyntax)namespaceDeclration.Members[0]; 7 var myDesignerClass = new CodeTypeDeclaration(designClassDeclaration.Identifier.ToString()); 8 var initializeComponent = new CodeMemberMethod(); 9 var ns = new CodeNamespace(namespaceDeclration.Name.ToString()); 10 11 foreach (var m in designClassDeclaration.Members) 12 { 13 14 if (m is ConstructorDeclarationSyntax) 15 { 16 var ctor = ((ConstructorDeclarationSyntax)m); 17 var codeBody = ctor.Body.ToString(); 18 codeBody = codeBody.Trim().TrimStart('{').TrimEnd('}').Trim().TrimEnd(';'); 19 CodeSnippetExpression csbody = new CodeSnippetExpression(codeBody); 20 CodeExpressionStatement stmt = new CodeExpressionStatement(csbody); 21 //Add the expression statements to the method. 22 // InitializeComponent 23 var cctor = new CodeConstructor(); 24 cctor.Name = ctor.Identifier.ToString(); 25 //var cmm = new CodeMemberMethod(); 26 //cmm.Name = ctor.Identifier.ToString(); 27 //cmm.Attributes = GetCtoRAttrMapping(ctor); 28 //cmm.ReturnType = new CodeTypeReference(typeof(void)); 29 cctor.Statements.Add(stmt); 30 31 myDesignerClass.Members.Add(cctor); 32 } 33 if (m is FieldDeclarationSyntax) 34 { 35 var F = ((FieldDeclarationSyntax)m); 36 var type = F.Declaration.Type; 37 foreach (var variable in F.Declaration.Variables) 38 { 39 var field = new CodeMemberField(); 40 field.Name = variable.Identifier.ToString(); 41 field.Type = new CodeTypeReference(type.ToString()); 42 field.Attributes = GetFieldAttrMapping(F); 43 //field.InitExpression = new CodePrimitiveExpression(null); 44 myDesignerClass.Members.Add(field); 45 } 46 } 47 if (m is MethodDeclarationSyntax) 48 { 49 var node = m as MethodDeclarationSyntax; 50 #region xml comments 51 var xmlTrivia = node.GetLeadingTrivia() 52 .Select(i => i.GetStructure()) 53 .OfType<DocumentationCommentTriviaSyntax>() 54 .FirstOrDefault(); 55 56 57 58 #endregion 59 60 61 62 var method = (MethodDeclarationSyntax)m; 63 64 var cmm = new CodeMemberMethod(); 65 cmm.Name = method.Identifier.ToString(); 66 67 68 69 ///XML注釋 70 string[] comments = xmlTrivia.ToString().Split("\r\n".ToCharArray()); 71 foreach (string text in comments) 72 { 73 if (text.Trim() != "") 74 { 75 cmm.Comments.Add(new CodeCommentStatement(text.Trim().TrimStart("http:///".ToCharArray()).Trim(), true)); 76 } 77 } 78 79 80 81 if (cmm.Name == "InitializeComponent") 82 { 83 //region 84 CodeRegionDirective codeRegion = new CodeRegionDirective(CodeRegionMode.Start, "Windows 窗體設(shè)計(jì)器生成的代碼"); 85 CodeRegionDirective codeEndRegion = new CodeRegionDirective(CodeRegionMode.End, ""); 86 87 cmm.StartDirectives.Add(codeRegion); 88 cmm.EndDirectives.Add(codeEndRegion); 89 } 90 91 //MemberAttributes.Family is protected 92 //cmm.Attributes = MemberAttributes.Override | MemberAttributes.Family; 93 cmm.Attributes = GetMethodAttrMapping(method); 94 cmm.ReturnType = new CodeTypeReference(method.ReturnType.ToString()); 95 96 foreach (var p in method.ParameterList.Parameters) 97 { 98 CodeParameterDeclarationExpression cpd = new CodeParameterDeclarationExpression(); 99 cpd.Name = p.Identifier.ToString();100 101 cpd.Type = new CodeTypeReference(p.Type.ToString());102 103 cmm.Parameters.Add(cpd);104 }105 //包含方法{};,會(huì)重復(fù)生成{};106 string codeBody = method.Body.ToString();107 codeBody = codeBody.Trim().TrimStart('{').TrimEnd('}').Trim().TrimEnd(';');108 if (codeBody != "")109 {110 CodeSnippetExpression csbody = new CodeSnippetExpression(codeBody);111 CodeExpressionStatement stmt = new CodeExpressionStatement(csbody);112 //Add the expression statements to the method.113 cmm.Statements.Add(stmt);114 }115 myDesignerClass.Members.Add(cmm);116 117 }118 if (m is MemberDeclarationSyntax)119 {120 121 }122 }123 124 ccu.Namespaces.Add(ns);125 126 //Partial Class127 myDesignerClass.IsPartial = true;128 129 130 ns.Types.Add(myDesignerClass);131 132 133 134 return ccu;135 }
窗體的顯示,需要逐句進(jìn)行C#解析,特別是InitializeComponent()方法。
.CS Code其實(shí)最簡單的就是讀取源代碼,然后返回就可以了。當(dāng)設(shè)計(jì)器添加控件或者綁定事件時(shí),可以通過文本操作進(jìn)行代碼完善。
1 //直接返回代碼,最簡單2 public string GetTextCSCode()3 {4 Flush();5 return __CSTextCode;6 }
CodeDomHostLoader類中有OnComponentRename,在設(shè)計(jì)器重命名組件時(shí)候響應(yīng),這里可以修復(fù)后臺(tái).cs中的控件引用
但此設(shè)計(jì)器還有很多不完善的地方,后期有時(shí)間再完善吧。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。
文章題目:C#用DesignSurface實(shí)現(xiàn)一個(gè)簡單的窗體設(shè)計(jì)器-創(chuàng)新互聯(lián)
文章出自:http://muchs.cn/article12/dodegc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)網(wǎng)站制作、虛擬主機(jī)、軟件開發(fā)、品牌網(wǎng)站制作、網(wǎng)站維護(hù)、移動(dòng)網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容