C#利用DesignSurface實現簡單的表單設計器的方法介紹(圖文)

來源:互聯網
上載者:User
這篇文章主要介紹了C#利用DesignSurface如何?簡單表單設計器的相關資料,文中通過圖文及範例程式碼介紹的很詳細,對大傢具有一定的參考價值,需要的朋友們下面來一起學習學習吧。

System.ComponentModel.Design.DesignSurface是為設計組件提供一個使用者介面,通過它可以實現一個簡單的表單設計器。

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

private void Form1_Load(object sender, EventArgs e) {  //引用System.Deisgn.dll  DesignSurface ds = new DesignSurface();  //開始載入表單  ds.BeginLoad(typeof(Form));  Control designerContorl = (Control)ds.View;  designerContorl.Dock = DockStyle.Fill;  this.Controls.Add(designerContorl); }

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

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

為了支援從原始碼載入初始化表單,需要對源碼中的相關方法進行解析,這裡我們 CodeDomDesignerLoader來實現定製化業務,CodeDomDesignerLoader是提供用於實現基於 CodeDOM 的設計器載入程式的基類。

繼承它的類需要重寫CodeCompileUnit Parse()方法,來實現載入表單:

protected override CodeCompileUnit Parse() {    #region 源檔案讀取  var sw = new StreamReader(@"E:\FrmUser.cs");  var sw_designer = new StreamReader(@"E:\FrmUser.Designer.cs");  string formCodeCS = sw.ReadToEnd();  string formCodeDesigner = sw_designer.ReadToEnd();  List<string> source = new List<string>();  source.Add(formCodeCS);  source.Add(formCodeDesigner);  #endregion  //Rolsyn解析C#  var rootDesigner = Source2CodeDom.Parse(formCodeDesigner);  codeDesingerCompileUnit = Source2CodeDom.GetDesignerCodeComplieUnit(rootDesigner);  var rootCS = Source2CodeDom.Parse(formCodeCS);  codeCSCompileUnit = Source2CodeDom.GetCodeComplieUnit(rootCS);  //MergeFormSource  string mergeS = Source2CodeDom.MergeFormSource(formCodeDesigner, formCodeCS);  codeMergeCompileUnit = Source2CodeDom.GetMergeDesignerCodeComplieUnit(mergeS);  return codeMergeCompileUnit;

解析的方法如下,但是此解析只是用於代碼的產生,並不能使用者UI介面的顯示:

public static CodeCompileUnit GetDesignerCodeComplieUnit2(CompilationUnitSyntax root) {  CodeCompileUnit ccu = new CodeCompileUnit();  var firstMember = root.Members[0];  var namespaceDeclration = (NamespaceDeclarationSyntax)firstMember;  var designClassDeclaration = (ClassDeclarationSyntax)namespaceDeclration.Members[0];  var myDesignerClass = new CodeTypeDeclaration(designClassDeclaration.Identifier.ToString());  var initializeComponent = new CodeMemberMethod();  var ns = new CodeNamespace(namespaceDeclration.Name.ToString());  foreach (var m in designClassDeclaration.Members)  {  if (m is ConstructorDeclarationSyntax)  {   var ctor = ((ConstructorDeclarationSyntax)m);   var codeBody = ctor.Body.ToString();   codeBody = codeBody.Trim().TrimStart('{').TrimEnd('}').Trim().TrimEnd(';');   CodeSnippetExpression csbody = new CodeSnippetExpression(codeBody);   CodeExpressionStatement stmt = new CodeExpressionStatement(csbody);   //Add the expression statements to the method.   // InitializeComponent   var cctor = new CodeConstructor();   cctor.Name = ctor.Identifier.ToString();   //var cmm = new CodeMemberMethod();   //cmm.Name = ctor.Identifier.ToString();   //cmm.Attributes = GetCtoRAttrMapping(ctor);   //cmm.ReturnType = new CodeTypeReference(typeof(void));   cctor.Statements.Add(stmt);   myDesignerClass.Members.Add(cctor);  }  if (m is FieldDeclarationSyntax)  {   var F = ((FieldDeclarationSyntax)m);   var type = F.Declaration.Type;   foreach (var variable in F.Declaration.Variables)   {   var field = new CodeMemberField();   field.Name = variable.Identifier.ToString();   field.Type = new CodeTypeReference(type.ToString());   field.Attributes = GetFieldAttrMapping(F);   //field.InitExpression = new CodePrimitiveExpression(null);   myDesignerClass.Members.Add(field);   }  }  if (m is MethodDeclarationSyntax)  {   var node = m as MethodDeclarationSyntax;   #region xml comments   var xmlTrivia = node.GetLeadingTrivia()   .Select(i => i.GetStructure())   .OfType<DocumentationCommentTriviaSyntax>()   .FirstOrDefault();    #endregion   var method = (MethodDeclarationSyntax)m;   var cmm = new CodeMemberMethod();   cmm.Name = method.Identifier.ToString();   ///XML注釋   string[] comments = xmlTrivia.ToString().Split("\r\n".ToCharArray());   foreach (string text in comments)   {   if (text.Trim() != "")   {    cmm.Comments.Add(new CodeCommentStatement(text.Trim().TrimStart("///".ToCharArray()).Trim(), true));   }   }   if (cmm.Name == "InitializeComponent")   {   //region    CodeRegionDirective codeRegion = new CodeRegionDirective(CodeRegionMode.Start, "Windows 表單設計器產生的程式碼");   CodeRegionDirective codeEndRegion = new CodeRegionDirective(CodeRegionMode.End, "");   cmm.StartDirectives.Add(codeRegion);   cmm.EndDirectives.Add(codeEndRegion);   }   //MemberAttributes.Family is protected   //cmm.Attributes = MemberAttributes.Override | MemberAttributes.Family;   cmm.Attributes = GetMethodAttrMapping(method);   cmm.ReturnType = new CodeTypeReference(method.ReturnType.ToString());   foreach (var p in method.ParameterList.Parameters)   {   CodeParameterDeclarationExpression cpd = new CodeParameterDeclarationExpression();   cpd.Name = p.Identifier.ToString();   cpd.Type = new CodeTypeReference(p.Type.ToString());   cmm.Parameters.Add(cpd);   }   //包含方法{};,會重複產生{};   string codeBody = method.Body.ToString();   codeBody = codeBody.Trim().TrimStart('{').TrimEnd('}').Trim().TrimEnd(';');   if (codeBody != "")   {   CodeSnippetExpression csbody = new CodeSnippetExpression(codeBody);   CodeExpressionStatement stmt = new CodeExpressionStatement(csbody);   //Add the expression statements to the method.   cmm.Statements.Add(stmt);   }   myDesignerClass.Members.Add(cmm);  }  if (m is MemberDeclarationSyntax)  {  }  }  ccu.Namespaces.Add(ns);  //Partial Class  myDesignerClass.IsPartial = true;   ns.Types.Add(myDesignerClass);    return ccu; }

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

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


 //直接傳回碼,最簡單 public string GetTextCSCode() { Flush(); return CSTextCode; }

CodeDomHostLoader類中有OnComponentRename,在設計器重新命名群組件時候響應,這裡可以修複後台.cs中的控制項引用

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

總結

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.