This article mainly introduces the use of C # DesignSurface How to implement a simple form designer of the relevant information, text and sample code through the introduction of a very detailed, for everyone has a certain reference value, the need for friends below to learn together.
System.ComponentModel.Design.DesignSurface
is to provide a user interface for designing components that enables a simple form designer.
Before we build it, we need to introduce System.Design.dll
it, or we'll see a designsurface error.
private void Form1_Load (object sender, EventArgs e) { //reference System.Deisgn.dll designsurface ds = new DesignSurface (); Start loading Form ds. BeginLoad (typeof (Form)); Control Designercontorl = (Control) ds. View; Designercontorl.dock = DockStyle.Fill; This. Controls.Add (DESIGNERCONTORL); }
A simple UI designer appears after the run
However, the designer does not implement the control drag-and-Drop and UI designer, as well as the control's property configuration.
In order to support the loading of the initialization form from the source code, we need to parse the relevant methods in the source, here we codedomdesignerloader to implement the custom business, CodeDomDesignerLoader is provided to implement the CodeDOM-based The base class for the designer loader.
The class that inherits it needs to override the CodeCompileUnit Parse()
method to implement the load form:
protected override CodeCompileUnit Parse () { #region source file reads 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 parsing 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;
The
Resolves the following methods, but this resolution is only for the generation of code and does not display the user UI interface:
public static CodeCompileUnit GetDesignerCodeComplieUnit2 (Compilationunitsyntax root) {CodeCompileUnit CCU = new CodeCo Mpileunit (); 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-constructordeclarationsyntax) {var ctor = (Constructor Declarationsyntax) 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 comment 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.S Tart, "Windows Forms Designer generated Code"); 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); }//contains method {}; {} will be generated repeatedly; 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; }
The display of the form, you need to step through C # parsing, especially the InitializeComponent()
method.
The simplest thing about. CS code is to read the source code and then return to it. When a designer adds a control or binds an event, it can be well-coded with text operations.
The direct return code, the simplest public string Gettextcscode () {Flush (); return cstextcode;}
The Codedomhostloader class has oncomponentrename, which responds when the designer renames the component, which can be repaired in the background. Control references in CS
But there are many imperfections in this designer, and there is time to improve it later.
Summarize