如果我理解正确,您希望为自定义类的事件提供一种在 VS IDE 属性编辑器中显示的方式。
这可以相当简单地完成,只需对您的类进行一些更改。首先,您需要了解 VS 实际上会编译您的表单以供 IDE 设计器使用。具体来说,InitializeComponent 中的所有设计器代码都需要编译才能创建/绘制表单。
这意味着为了让您的类事件(和道具)在 IDE 中显示,您的类需要是 Component(或 Control),以便可以像其他任何类型一样为 IDE 属性编辑器编译它.它不能是您在运行时实例化的类,因为表单编辑器不会检查该代码。
我已经用其他类在运行时充当普通类但增加了通过 from 设计器在 IDE 中设置属性等的能力(例如,具有ExtenderProvider 能力的类) .对您的班级的更改从以下内容开始:
class Validator:Component, ISupportInitialize
{
// fake props
public string Foo { get; set; }
public int Bar { get; set; }
public event ValidatingEventHandler Validating;
public delegate void ValidatingEventHandler(object sender, EventArgs e);
public event ValidatedEventHandler Validated;
public delegate void ValidatedEventHandler(object sender, EventArgs e);
public Validator(string foo, int bar)
{
}
public Validator()
{
}
// ISupportInitialize methods
public void BeginInit()
{
}
public void EndInit()
{
}
}
编译和验证器将在工具箱中可用。将一个拖到窗体/组件托盘。选择它,打开属性编辑器 et voila IDE 中显示的属性和事件:
验证器组件属性 (click for larger image)。事件视图:
双击所需的事件,VS 会添加骨架事件处理程序供您编辑。
组件的保养和喂养
只需让您的类从 Component 继承即可完成大部分工作。有一些与组件相关的东西是必需的或可能出现的。其中大部分都是简单的问题和修复。
简单的向量
作为一个组件,你的 Validator 类必须有一个简单的(无参数的)ctor。 VS 不知道如何使用上面的(string foo, int bar) 版本来实例化它。
如果您的代码依赖于这些参数来初始化构造函数中的其他内容,这可能会导致问题。答案是ISupportIntialize。
ISupportInitialize
此接口支持 VS 将从设计器代码调用的 BeginInit 和 EndInit 方法,因为它现在负责设置组件的属性:
//
// validator1
//
this.validator1.Bar = 0;
this.validator1.Foo = null;
this.validator1.Validating += new Validator.ValidatingEventHandler(this.validator1_Validating);
...
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.tableLayoutPanel1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.validator1)).EndInit();
this.ResumeLayout(false);
...
private Validator validator1; // note: no params
如您所见,设计器代码所做的最后一件事是,在设置完所有属性后,在您的类/组件上调用 EndInit。任何使用foo 或bar 的初始化ctor 代码都可以简单地移到那里。
属性
您的类的属性和事件现在将显示在 IDE 中。如果您希望隐藏其中的任何一个(也许它仅在需要验证实际项目时才有意义),您可以使用 Browsable 属性阻止它们显示在属性窗格中:
[Browsable(false)]
public string Foo { get; set; }
为了确定 VS 确实序列化您希望通过 IDE 管理的那些,请使用 DesignerSerialization 属性:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int Bar { get; set; }
对于您不希望 VS 序列化的任何属性,请使用 DesignerSerializationVisibility.Hidden。
最后,OP 提到了 Validator 处理的“项目集合”。如果 Validator 上有一个集合类属性(例如Items),则会显示该属性的默认集合编辑器。这可能是可取的,也可能不是可取的,具体取决于项目是什么。您可以在此[Browsable(false)] 隐藏它。
如果您确实希望通过 IDE 添加/编辑项目,还有更多工作要做,但那是另一回事。
附录
这是关于访问 CollectionEditor 中的项目事件的新的、新兴的愿望,并且(显然)在单击时为它们创建了代码(在哪里创建,我不确定)。这在设计和实践中都存在许多问题。我假设这样的结构:
Form.Validator.Items<ValidationItems>
首先,CollectionEditor 中使用的属性网格是一个内部网格。在EditorForm 上不难找到,但仅仅启用事件视图并不会神奇地赋予它在单击事件时知道该做什么的能力。由于它与集合一起工作,它对拥有集合的 Type 知之甚少,对承载该 Type 的 Form 知之甚少。
CollectionEditor 中的事件视图已关闭,因为它无法将事件代码添加到表单(Items 的曾祖父对象!),因为没有要引用的表单级对象。它不能/不会将事件添加到您的集合类代码中,因为您的代码没有设计器文件。最后,集合属性的主要要求是集合实现IList。如果您的集合属性是普通列表或集合变量,则没有可供修改的代码文件。
要为需要重新配置的项目启用表单事件。作为一个项目类,它们“属于”其他东西——验证器类/组件。如果 Items 也被重做为 Component,表单级事件成为可能:
[Serializable]
public class ValidationItem: Component
{
[DefaultValue("")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string DisplayName { get; set; }
[DefaultValue(-1)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int Value { get; set; }
public event ValidatingEventHandler Validating;
public delegate void ValidatingEventHandler(object sender, EventArgs e);
public ValidationItem()
{
Name = "New Item";
Value = 0;
}
}
现在,Items 将作为表单组件存在并存储在 Validator 的 Items 集合中 - 类似于 DataGridView 的列。要编辑/添加事件,您仍然不能从 CollectionEditor 执行此操作,原因与之前相同,但它们可从 IDE 属性窗口中使用。
选择项目组件并像往常一样使用属性窗口将事件代码添加到设计器和表单(非常类似于原始中的Validator 组件):
// (Designer)
// validationItem1
//
this.validationItem1.DisplayName = "New Item";
this.validationItem1.Value = 0;
this.validationItem1.Validating += new ValidationItem.ValidatingEventHandler(this.validationItem1_Validating);
...
private ValidationItem validationItem1; // persistent form var
形式:
private void validationItem1_Validating(object sender, EventArgs e)
{
}
作为一个组件,之前关于它们的所有要点现在也适用于项目。
缺点
a) 如果项目很多,组件托盘中会有很多ValidationItems。我要问自己的第一件事是我是否需要验证器类和所有这些项目作为单独的表单级对象。
b) 与控件一样,如果您删除一个,它将从设计器中删除代码,但不会从表单中删除。当您更改/更新您的项目时,可能会导致重复的代码(收藏内容往往更不稳定):
private void validationItem1_Validating(object sender, EventArgs e)
...
private void validationItem1_Validating_1(object sender, EventArgs e)
...
private void validationItem1_Validating_2(object sender, EventArgs e)
这种方法对我来说似乎“嘈杂”。 CollectionClass 完全能够连接到 Items 的事件,然后以单个 Validator 事件的形式冒泡到表单中。为什么要维护 15 甚至 5 个事件,而一个事件可以工作?不应该将所有这些整合到Validator 类的工作中吗?例如:
private void validator1_ValidationComplete(object sender,
ValidationCompleteEventArgs e)
{
}
ValidationCompleteEventArgs 可以报告哪些项目已验证或未验证、何时验证、为什么验证、提供CancelRemaining 功能或表单需要知道的任何内容。这与 ListBox 或 DataGridView 没有什么不同,它们代表它包含的内容报告事件。