이 글에서는 DesignSurface를 사용하여 간단한 폼 디자이너를 구현하는 방법에 대한 C# 관련 정보를 주로 소개합니다. 이 글에서는 이를 그림, 텍스트 및 샘플 코드를 통해 자세히 소개합니다. 친구가 필요합니다. 와서 함께 공부하세요.
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를 사용하여 맞춤형 서비스를 구현하는 기반을 제공합니다. 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 코드는 소스 코드를 읽고 반환하는 것이 가장 간단합니다. 디자이너가 컨트롤을 추가하거나 이벤트를 바인딩하면 텍스트 작업을 통해 코드를 완성할 수 있습니다.
//直接返回代码,最简单 public string GetTextCSCode() { Flush(); return CSTextCode; }
CodeDomHostLoader 클래스에는 디자이너가 구성 요소의 이름을 바꿀 때 응답하는 OnComponentRename이 있습니다. 여기에서 백그라운드 .cs
그런데 이 디자이너는 아직 부족한 부분이 많은데, 나중에 시간이 나면 개선해 나가겠습니다.
요약
위 내용은 DesignSurface를 사용하여 C#으로 간단한 폼 디자이너를 구현하는 방법 소개(그림 및 텍스트)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!