Я нашел пример ControlDesigner, который показал мне, как добавить элементы управления и создать обработчик событий с помощью IEventBindingService
, а затем добавить код в обработчик этого события, используя CodeTypeDeclaration
. Но когда я попытался получить доступ к пользовательским атрибутам базовой формы, CodeTypeDeclaration
вернул пустую коллекцию. Следующий пример показывает, что CodeTypeDeclaration
не возвращает пользовательские атрибуты базовой формы:Пользовательские атрибуты Access Form во время разработки
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));
}
}
}
Я попытался с помощью пользовательских CodeDomSerializer
для моей формы, но с таким подходом я могу только код доступа в InitializeComponent
методе. Есть ли другой способ доступа к пользовательским атрибутам моей формы?
Причина, по которой я хочу, чтобы я мог создать действие в конструкторе, чтобы добавить/изменить параметры моего пользовательского атрибута в форме.