好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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中的控件引用

 

但此设计器还有很多不完善的地方,后期有时间再完善吧。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

原文链接:http://www.cnblogs.com/isaboy/p/DesignSurface.html

dy("nrwz");

查看更多关于C#利用DesignSurface如何实现简单的窗体设计器的详细内容...

  阅读:47次