ホームページ  >  記事  >  バックエンド開発  >  DesignSurfaceを使ってC#で簡易フォームデザイナーを実装する方法の紹介(画像とテキスト)

DesignSurfaceを使ってC#で簡易フォームデザイナーを実装する方法の紹介(画像とテキスト)

黄舟
黄舟オリジナル
2017-03-17 13:14:584831ブラウズ

この記事では、C#DesignSurface を使用して簡単なフォーム デザイナーを実装する方法について詳しく紹介します。必要な方は必ず参考にしてください。勉強して勉強してください。

System.ComponentModel.Design.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(&#39;{&#39;).TrimEnd(&#39;}&#39;).Trim().TrimEnd(&#39;;&#39;);
   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(&#39;{&#39;).TrimEnd(&#39;}&#39;).Trim().TrimEnd(&#39;;&#39;);
   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()

ビルドする前に、System.Design.dll を導入する必要があります。そうしないと、DesignSurface が見つからないというエラーが発生します。

 //直接返回代码,最简单
 public string GetTextCSCode()
 {
 Flush();
 return CSTextCode;
 }

実行するとシンプルなUIデザインが表示されます

ただし、デザイナーはコントロールを実装できません ドラッグ アンド ドロップUI デザイナー、およびコントロールのプロパティ構成。

ソース コードからの初期化フォームの読み込みをサポートするには、ソース コード内の関連メソッドを解析する必要があります。ここでは、CodeDomDesignerLoader を使用して、カスタマイズされたサービスを実装します。CodeDomDesignerLoader は、デザイナーを実装するための基本クラスを提供します。 CodeDOM に基づくローダー。


継承

そのクラスは CodeCompileUnit Parse() メソッドをオーバーライドする必要があります。読み込みフォームを実装するには:

rrreee

解析方法は次のとおりですが、この解析はコード生成のみに使用され、ユーザー UI インターフェイスを表示することはできません:

rrreee フォームの表示には、特に文ごとに C# 解析が必要ですInitializeComponent() メソッド。

。CS コードは、実際にはソース コードを読んで返すのが最も簡単です。デザイナーがコントロールを追加したり、

イベント

をバインドしたりする場合、テキスト操作を通じてコードを改善できます。

🎜rrreee🎜CodeDomHostLoader クラスには、デザイナーがコンポーネントの名前を変更したときに応答する OnComponentRename があります。ここで、バックグラウンドでコントロール参照を修正できます。しかし、このデザイナーにはまだ多くの不完全な点があります。後で改善する時間があります。 🎜🎜🎜概要🎜🎜

以上がDesignSurfaceを使ってC#で簡易フォームデザイナーを実装する方法の紹介(画像とテキスト)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。