C#用DesignSurface實現一個簡單的窗體設計器

System.ComponentModel.Design.DesignSurface是為設計組件提供一個用戶界面,通過它可以實現一個簡單的窗體設計器。

創(chuàng)新互聯建站成立于2013年,我們提供高端網站建設公司成都網站制作、成都網站設計、網站定制、營銷型網站建設、微信平臺小程序開發(fā)、微信公眾號開發(fā)、營銷推廣服務,提供專業(yè)營銷思路、內容策劃、視覺設計、程序開發(fā)來完成項目落地,為隧道混凝土攪拌車企業(yè)提供源源不斷的流量和訂單咨詢。

    在構建之前,我們需要引入System.Design.dll,否則會出現找不到DesignSurface的錯誤。

 C#用DesignSurface實現一個簡單的窗體設計器

 C#用DesignSurface實現一個簡單的窗體設計器

 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         }

 C#用DesignSurface實現一個簡單的窗體設計器

運行后出現簡單的一個UI設計器

 C#用DesignSurface實現一個簡單的窗體設計器

但是該設計器并不能實現控件拖放和UI設計器,以及控件的屬性配置。

為了支持從源代碼加載初始化窗體,需要對源碼中的相關方法進行解析,這里我們 CodeDomDesignerLoader來實現定制化業(yè)務,CodeDomDesignerLoader是提供用于實現基于 CodeDOM 的設計器加載程序的基類。

繼承它的類需要重寫CodeCompileUnit Parse()方法,來實現加載窗體:

 C#用DesignSurface實現一個簡單的窗體設計器

 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;

 C#用DesignSurface實現一個簡單的窗體設計器

解析的方法如下,但是此解析只是用于代碼的生成,并不能用戶UI界面的顯示:

 C#用DesignSurface實現一個簡單的窗體設計器

  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 窗體設計器生成的代碼"); 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                     //包含方法{};,會重復生成{};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         }

 C#用DesignSurface實現一個簡單的窗體設計器

 窗體的顯示,需要逐句進行C#解析,特別是InitializeComponent()方法。

 C#用DesignSurface實現一個簡單的窗體設計器

 C#用DesignSurface實現一個簡單的窗體設計器

.CS Code其實最簡單的就是讀取源代碼,然后返回就可以了。當設計器添加控件或者綁定事件時,可以通過文本操作進行代碼完善。

1 //直接返回代碼,最簡單2  public string GetTextCSCode()3  {4        Flush();5        return __CSTextCode;6 }

CodeDomHostLoader類中有OnComponentRename,在設計器重命名組件時候響應,這里可以修復后臺.cs中的控件引用

 C#用DesignSurface實現一個簡單的窗體設計器

 C#用DesignSurface實現一個簡單的窗體設計器

 C#用DesignSurface實現一個簡單的窗體設計器

 

 但此設計器還有很多不完善的地方,后期有時間再完善吧。

網頁題目:C#用DesignSurface實現一個簡單的窗體設計器
鏈接分享:http://muchs.cn/article40/jcpieo.html

成都網站建設公司_創(chuàng)新互聯,為您提供商城網站靜態(tài)網站、網站設計、外貿建站、響應式網站App開發(fā)

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯

成都定制網站網頁設計