溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

C#用DesignSurface實現(xiàn)一個簡單的窗體設(shè)計器

發(fā)布時間:2020-07-12 18:13:49 來源:網(wǎng)絡(luò) 閱讀:558 作者:26度出太陽 欄目:網(wǎng)絡(luò)安全

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

    在構(gòu)建之前,我們需要引入System.Design.dll,否則會出現(xiàn)找不到DesignSurface的錯誤。

 C#用DesignSurface實現(xiàn)一個簡單的窗體設(shè)計器

 C#用DesignSurface實現(xiàn)一個簡單的窗體設(shè)計器

 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實現(xiàn)一個簡單的窗體設(shè)計器

運行后出現(xiàn)簡單的一個UI設(shè)計器

 C#用DesignSurface實現(xiàn)一個簡單的窗體設(shè)計器

但是該設(shè)計器并不能實現(xiàn)控件拖放和UI設(shè)計器,以及控件的屬性配置。

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

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

 C#用DesignSurface實現(xiàn)一個簡單的窗體設(shè)計器

 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實現(xiàn)一個簡單的窗體設(shè)計器

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

 C#用DesignSurface實現(xiàn)一個簡單的窗體設(shè)計器

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

 C#用DesignSurface實現(xiàn)一個簡單的窗體設(shè)計器

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

 C#用DesignSurface實現(xiàn)一個簡單的窗體設(shè)計器

 C#用DesignSurface實現(xiàn)一個簡單的窗體設(shè)計器

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

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

CodeDomHostLoader類中有OnComponentRename,在設(shè)計器重命名組件時候響應(yīng),這里可以修復(fù)后臺.cs中的控件引用

 C#用DesignSurface實現(xiàn)一個簡單的窗體設(shè)計器

 C#用DesignSurface實現(xiàn)一個簡單的窗體設(shè)計器

 C#用DesignSurface實現(xiàn)一個簡單的窗體設(shè)計器

 

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


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI