C#利用DesignSurface如何實現(xiàn)簡單的窗體設(shè)計器
System.ComponentModel.Design.DesignSurface是為設(shè)計組件提供一個用戶界面,通過它可以實現(xiàn)一個簡單的窗體設(shè)計器。
在構(gòu)建之前,我們需要引入System.Design.dll,否則會出現(xiàn)找不到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);
}
運行后出現(xiàn)簡單的一個UI設(shè)計器
但是該設(shè)計器并不能實現(xiàn)控件拖放和UI設(shè)計器,以及控件的屬性配置。
為了支持從源代碼加載初始化窗體,需要對源碼中的相關(guān)方法進行解析,這里我們 CodeDomDesignerLoader來實現(xiàn)定制化業(yè)務(wù),CodeDomDesignerLoader是提供用于實現(xiàn)基于 CodeDOM 的設(shè)計器加載程序的基類。
繼承它的類需要重寫CodeCompileUnit Parse()方法,來實現(xiàn)加載窗體:
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("http:///".ToCharArray()).Trim(), true));
}
}
if (cmm.Name == "InitializeComponent")
{
//region
CodeRegionDirective codeRegion = new CodeRegionDirective(CodeRegionMode.Start, "Windows 窗體設(shè)計器生成的代碼");
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其實最簡單的就是讀取源代碼,然后返回就可以了。當設(shè)計器添加控件或者綁定事件時,可以通過文本操作進行代碼完善。
//直接返回代碼,最簡單
public string GetTextCSCode()
{
Flush();
return __CSTextCode;
}
CodeDomHostLoader類中有OnComponentRename,在設(shè)計器重命名組件時候響應,這里可以修復后臺.cs中的控件引用
但此設(shè)計器還有很多不完善的地方,后期有時間再完善吧。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流。
欄 目:C#教程
本文標題:C#利用DesignSurface如何實現(xiàn)簡單的窗體設(shè)計器
本文地址:http://www.jygsgssxh.com/a1/C_jiaocheng/5868.html
您可能感興趣的文章
- 01-10Extjs4如何處理后臺json數(shù)據(jù)中日期和時間
- 01-10asp.net中XML如何做增刪改查操作
- 01-10C#利用反射技術(shù)實現(xiàn)去掉按鈕選中時的邊框效果
- 01-10C#圖片處理3種高級應用
- 01-10C#.NET中如何批量插入大量數(shù)據(jù)到數(shù)據(jù)庫中
- 01-10C#異步下載文件
- 01-10C# Console利用mspaint打開圖像并保存的方法
- 01-10C#利用delegate實現(xiàn)Javascript的each方法
- 01-10解析C#中的常量及如何在C#編程中定義常量
- 01-10如何使用C#從word文檔中提取圖片


閱讀排行
本欄相關(guān)
- 01-10C#通過反射獲取當前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁無法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實現(xiàn)txt定位指定行完整實例
- 01-10WinForm實現(xiàn)仿視頻播放器左下角滾動新
- 01-10C#停止線程的方法
- 01-10C#實現(xiàn)清空回收站的方法
- 01-10C#通過重寫Panel改變邊框顏色與寬度的
- 01-10C#實現(xiàn)讀取注冊表監(jiān)控當前操作系統(tǒng)已
隨機閱讀
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10delphi制作wav文件的方法
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 04-02jquery與jsp,用jquery
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-10C#中split用法實例總結(jié)
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-11ajax實現(xiàn)頁面的局部加載


