C# 在设计时访问表单自定义属性
我找到了ControlDesigner的一个示例,它向我展示了如何使用C# 在设计时访问表单自定义属性,c#,winforms,custom-attributes,design-time,C#,Winforms,Custom Attributes,Design Time,我找到了ControlDesigner的一个示例,它向我展示了如何使用IEventBindingService添加控件和创建事件处理程序,然后使用CodeTypeDeclaration在该事件处理程序中添加一些代码。但是当我试图访问基本表单的自定义属性时,codetypedesclaration返回了一个空集合。以下示例显示CodeTypeDeclaration不返回基本表单的任何自定义属性: using System; using System.CodeDom; using System.Co
IEventBindingService
添加控件和创建事件处理程序,然后使用CodeTypeDeclaration
在该事件处理程序中添加一些代码。但是当我试图访问基本表单的自定义属性时,codetypedesclaration
返回了一个空集合。以下示例显示CodeTypeDeclaration
不返回基本表单的任何自定义属性:
using System;
using System.CodeDom;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
namespace WindowsFormsApplication1
{
[MyCustom("new sample text")]
public class MyForm : MyBaseForm
{
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// MyForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.ClientSize = new System.Drawing.Size(617, 450);
this.ResumeLayout(false);
}
#endregion
public MyForm()
{
InitializeComponent();
}
}
[MyCustom("sample text")]
[Designer(typeof(MyBaseFormDesigner), typeof(IRootDesigner))]
public partial class MyBaseForm : Form
{
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// MyBaseForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(391, 337);
this.ResumeLayout(false);
}
#endregion
public MyBaseForm()
{
InitializeComponent();
}
}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class MyCustomAttribute : Attribute
{
public string Text { get; set; }
public MyCustomAttribute(string text)
{
this.Text = text;
}
}
public class MyBaseFormDesigner : DocumentDesigner
{
public override void Initialize(IComponent component)
{
base.Initialize(component);
Verbs.Add(new DesignerVerb("Show CodeTypeDeclaration", OnShowCodeTypeDeclaration));
}
private static string GetCode(CodeTypeDeclaration codeType)
{
var code = new System.Text.StringBuilder();
using (var provider = new Microsoft.CSharp.CSharpCodeProvider()) {
using (var writer = new System.IO.StringWriter(code)) {
provider.GenerateCodeFromType(codeType, writer, new System.CodeDom.Compiler.CodeGeneratorOptions());
}
}
return code.ToString();
}
protected virtual void OnShowCodeTypeDeclaration(object sender, EventArgs args)
{
var codeType = GetService(typeof(CodeTypeDeclaration)) as CodeTypeDeclaration;
if (MessageBox.Show("Add MyCustomAttribute?", "", MessageBoxButtons.YesNo) == DialogResult.Yes) {
codeType.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(MyCustomAttribute)), new CodeAttributeArgument(new CodePrimitiveExpression("sample text from designer"))));
}
MessageBox.Show(GetCode(codeType));
}
}
}
使用系统;
使用System.CodeDom;
使用系统组件模型;
使用System.ComponentModel.Design;
使用System.Windows.Forms;
使用System.Windows.Forms.Design;
命名空间Windows窗体应用程序1
{
[MyCustom(“新示例文本”)]
公共类MyForm:MyBaseForm
{
#区域Windows窗体设计器生成的代码
///
///设计器支持所需的方法-不修改
///此方法的内容与代码编辑器一起使用。
///
私有void InitializeComponent()
{
这个.SuspendLayout();
//
//MyForm
//
此.AutoScaleDimensions=新系统.Drawing.SizeF(6F,13F);
this.ClientSize=新系统图纸尺寸(617450);
此选项为.resume布局(false);
}
#端区
公共MyForm()
{
初始化组件();
}
}
[MyCustom(“示例文本”)]
[Designer(typeof(MyBaseFormDesigner)、typeof(IRootDesigner))]
公共部分类MyBaseForm:Form
{
#区域Windows窗体设计器生成的代码
///
///设计器支持所需的方法-不修改
///此方法的内容与代码编辑器一起使用。
///
私有void InitializeComponent()
{
这个.SuspendLayout();
//
//MyBaseForm
//
此.AutoScaleDimensions=新系统.Drawing.SizeF(6F,13F);
this.AutoScaleMode=System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize=新系统.Drawing.Size(391337);
此选项为.resume布局(false);
}
#端区
公共MyBaseForm()
{
初始化组件();
}
}
[AttributeUsage(AttributeTargets.Class,AllowMultiple=true,Inherited=true)]
公共类MyCustomAttribute:属性
{
公共字符串文本{get;set;}
公共MyCustomAttribute(字符串文本)
{
this.Text=文本;
}
}
公共类MyBaseFormDesigner:DocumentDesigner
{
公共覆盖无效初始化(IComponent组件)
{
初始化(组件);
添加(新的DesignerB(“ShowCodeTypeDeclaration”,OnShowCodeTypeDeclaration));
}
私有静态字符串GetCode(CodeTypeDeclaration codeType)
{
var code=new System.Text.StringBuilder();
使用(var provider=new Microsoft.CSharp.CSharpCodeProvider()){
使用(var writer=new System.IO.StringWriter(代码)){
provider.GenerateCodeFromType(codeType、writer、new System.CodeDom.Compiler.CodeGeneratorOptions());
}
}
返回代码.ToString();
}
ShowCodeTypeDeclaration上受保护的虚拟无效(对象发送方、事件args args)
{
var codeType=GetService(typeof(CodeTypeDeclaration))作为CodeTypeDeclaration;
if(MessageBox.Show(“添加MyCustomAttribute?”,“”,MessageBoxButtons.YesNo)=DialogResult.Yes){
添加(新的CodeAttributeDeclaration(新的CodeTypeReference(typeof(MyCustomAttribute)),新的CodeAttributeArgument(新的CodePrimitiveExpression(“来自设计器的示例文本”))));
}
Show(GetCode(codeType));
}
}
}
我尝试在表单中使用自定义CodeDomSerializer
,但使用这种方法,我只能访问InitializeComponent
方法中的代码。是否有其他方法可以访问表单的自定义属性
我之所以希望这样做,是因为我可以在designer中创建一个操作,在表单上添加/更改自定义属性的参数。我终于找到了我要查找的内容,使用EnvDTE可以访问属性(和导入)。下面是我可以添加/更改属性值的完整示例:
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
namespace WindowsFormsApplication1
{
[MyCustom("new sample text")]
public class MyForm : MyBaseForm
{
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// MyForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.ClientSize = new System.Drawing.Size(617, 450);
this.ResumeLayout(false);
}
#endregion
public MyForm()
{
InitializeComponent();
}
}
[MyCustom("sample text")]
[Designer(typeof(MyBaseFormDesigner), typeof(IRootDesigner))]
public partial class MyBaseForm : Form
{
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// MyBaseForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(391, 337);
this.ResumeLayout(false);
}
#endregion
public MyBaseForm()
{
InitializeComponent();
}
}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class MyCustomAttribute : Attribute
{
public string Text { get; set; }
public MyCustomAttribute(string text = "")
{
this.Text = text;
}
}
public class MyBaseFormDesigner : DocumentDesigner
{
public override void Initialize(IComponent component)
{
base.Initialize(component);
Verbs.Add(new DesignerVerb("Edit MyCustomAttribute text", OnEditText));
}
protected virtual void OnEditText(object sender, EventArgs args)
{
EnvDTE._DTE dte = GetService(typeof(EnvDTE._DTE)) as EnvDTE._DTE;
EnvDTE80.CodeClass2 codeClass = GetCodeClass(dte.ActiveDocument.ProjectItem.FileCodeModel.CodeElements, "MyForm");
EnvDTE80.CodeAttribute2 codeAttribute = GetCodeAttribute(codeClass, "MyCustom");
if (codeAttribute != null) {
string newValue = Microsoft.VisualBasic.Interaction.InputBox("Current Text", "Edit MyCustomAttribute text", RemoveQuote(codeAttribute.Value), -1, -1);
codeAttribute.Value = (!string.IsNullOrWhiteSpace(newValue) ? "\"" + newValue + "\"" : "");
}
}
private static string RemoveQuote(string str)
{
return !string.IsNullOrEmpty(str) && str[0] == '"' && str[str.Length - 1] == '"' ? str.Substring(1, str.Length - 2) : str;
}
private static EnvDTE80.CodeClass2 GetCodeClass(EnvDTE.CodeElements codeElements, string className)
{
if (codeElements != null) {
foreach (EnvDTE.CodeElement item in codeElements) {
if (item.Kind == EnvDTE.vsCMElement.vsCMElementClass) {
EnvDTE80.CodeClass2 codeClass = item as EnvDTE80.CodeClass2;
if (codeClass != null && codeClass.Name == className) return codeClass;
} else if (item.Kind == EnvDTE.vsCMElement.vsCMElementNamespace) {
EnvDTE80.CodeClass2 codeClass = GetCodeClass(((EnvDTE.CodeNamespace)item).Members, className);
if (codeClass != null && codeClass.Name == className) return codeClass;
}
}
}
return null;
}
private static EnvDTE80.CodeAttribute2 GetCodeAttribute(EnvDTE80.CodeClass2 codeClass, string attributeName)
{
if (codeClass != null) {
foreach (EnvDTE80.CodeAttribute2 attr in codeClass.Attributes) {
if (attr.Name == attributeName) return attr;
}
return codeClass.AddAttribute(attributeName, "") as EnvDTE80.CodeAttribute2;
}
return null;
}
}
}
使用系统;
使用系统组件模型;
使用System.ComponentModel.Design;
使用System.Windows.Forms;
使用System.Windows.Forms.Design;
命名空间Windows窗体应用程序1
{
[MyCustom(“新示例文本”)]
公共类MyForm:MyBaseForm
{
#区域Windows窗体设计器生成的代码
///
///设计器支持所需的方法-不修改
///此方法的内容与代码编辑器一起使用。
///
私有void InitializeComponent()
{
这个.SuspendLayout();
//
//MyForm
//
此.AutoScaleDimensions=新系统.Drawing.SizeF(6F,13F);
this.ClientSize=新系统图纸尺寸(617450);
此选项为.resume布局(false);
}
#端区
公共MyForm()
{
初始化组件();
}
}
[MyCustom(“示例文本”)]
[Designer(typeof(MyBaseFormDesigner)、typeof(IRootDesigner))]
公共部分类MyBaseForm:Form
{
#区域Windows窗体设计器生成的代码
///
///设计器支持所需的方法-不修改
///此方法的内容与代码编辑器一起使用。
///
私有void InitializeComponent()
{
这个.SuspendLayout();
//
//MyBaseForm
//
此.AutoScaleDimensions=新系统.Drawing.SizeF(6F,13F);
this.AutoScaleMode=System.Window