首先,您需要在您的类中声明事件(连同您的方法和构造函数):
public event EventHandler LabelsTextChanged;
然后您需要创建一个方法来处理各个标签的TextChanged 事件。
private void HandleLabelTextChanged(object sender, EventArgs e)
{
// we'll explain this in a minute
this.OnLabelsTextChanged(EventArgs.Empty);
}
某处,可能在您控件的构造函数中,您需要订阅标签的TextChanged 事件。
myLabel1.TextChanged += this.HandleLabelTextChanged;
myLabel2.TextChanged += this.HandleLabelTextChanged;
myLabel3.TextChanged += this.HandleLabelTextChanged;
现在是HandleLabelsTextChanged 方法。我们可以直接加注LabelsTextChanged;但是,.NET 框架设计指南说创建OnEventName 受保护的虚拟方法来为我们引发事件是最佳实践。这样,继承类可以通过重写OnEventName 方法来“处理”事件,结果证明这比订阅事件有更好的性能。即使您认为自己永远不会覆盖 OnEventName 方法,但还是养成这样做的习惯是个好主意,因为它可以简化事件引发过程。
这是我们的OnLabelsTextChanged:
protected virtual void OnLabelsTextChanged(EventArgs e)
{
EventHandler handler = this.LabelsTextChanged;
if (handler != null)
{
handler(this, e);
}
}
我们必须检查 null,因为没有订阅者的事件是 null。如果我们试图引发一个空事件,我们会得到一个NullReferenceException。请注意,我们将事件的EventHandler 复制到一个局部变量,然后再检查它是否为空并引发事件。如果我们改为这样做:
if (this.LabelsTextChanged != null)
{
this.LabelsTextChanged(this, e);
}
我们将在无效性检查和事件引发之间存在竞争条件。如果碰巧事件的订阅者在我们引发事件之前但在我们检查 null 之后取消订阅,则会引发异常。您通常不会遇到此问题,但最好养成以安全方式编写它的习惯。
编辑:下面是public event EventHandler LabelsTextChanged; 行的放置方式:
namespace YourNamespace
{
class MyUserControl : UserControl
{
// it needs to be here:
public event EventHandler LabelsTextChanged;
...
}
}
Here是事件设计的框架设计指南,供进一步阅读。