如何在C#中向UserControl添加事件?

如何在C#中向UserControl添加事件?,c#,winforms,events,user-controls,C#,Winforms,Events,User Controls,我有一个UserControl,它包含3个标签。我想为它添加一个事件,当其中一个标签的文本更改时会发生该事件。 我正在使用Visual Studio 2010首先,您应该在usercontrol中声明一个事件,例如: public delegate void TextChangedEventHandler(object sender, EventArgs e); public event TextChangedEventHandler LabelTextChanged; // ... pro

我有一个UserControl,它包含3个标签。我想为它添加一个事件,当其中一个标签的文本更改时会发生该事件。

我正在使用Visual Studio 2010

首先,您应该在usercontrol中声明一个事件,例如:

public delegate void TextChangedEventHandler(object sender, EventArgs e);
public event TextChangedEventHandler LabelTextChanged;

// ...

protected void MyTextBox_TextChanged(object sender, EventArgs e)
{
    if (LabelTextChanged != null) {
        LabelTextChanged(this, e);
    }
}
public event EventHandler TextOfLabelChanged;
然后,您必须在运行时调用绑定到事件(如果有)的回调函数。您可以通过如下方式处理标签的TextChanged事件:

public void LabelTextChanged(object sender,EventArgs e)
{
if(TextOfLabelChanged!=null)
TextOfLabelChanged(sender,e);
}
_myLabel.TextChanged+=LabelTextChanged;
if (this.LabelsTextChanged != null)
{
    this.LabelsTextChanged(this, e);
}
如果愿意,您可以拥有自己的EventArgs对象

在代码的某个地方,您应该将label TextChanged事件绑定到此方法,如下所示:

public void LabelTextChanged(object sender,EventArgs e)
{
if(TextOfLabelChanged!=null)
TextOfLabelChanged(sender,e);
}
_myLabel.TextChanged+=LabelTextChanged;
if (this.LabelsTextChanged != null)
{
    this.LabelsTextChanged(this, e);
}

首先,需要在类中声明事件(与方法和构造函数一起):

然后,您需要创建一个方法来处理单个标签的
TextChanged
事件

private void HandleLabelTextChanged(object sender, EventArgs e)
{
    // we'll explain this in a minute
    this.OnLabelsTextChanged(EventArgs.Empty);
}
myLabel1.TextChanged += this.HandleLabelTextChanged;
myLabel2.TextChanged += this.HandleLabelTextChanged;
myLabel3.TextChanged += this.HandleLabelTextChanged;
在某个地方,可能在控件的构造函数中,您需要订阅标签的
TextChanged
事件

private void HandleLabelTextChanged(object sender, EventArgs e)
{
    // we'll explain this in a minute
    this.OnLabelsTextChanged(EventArgs.Empty);
}
myLabel1.TextChanged += this.HandleLabelTextChanged;
myLabel2.TextChanged += this.HandleLabelTextChanged;
myLabel3.TextChanged += this.HandleLabelTextChanged;
现在来看
handleLabelTextChanged
方法。我们可以直接提出
标签textchanged
;然而,.NET framework设计指南指出,最好创建一个
OnEventName
受保护的虚拟方法来为我们引发事件。这样,继承类就可以通过重写
OnEventName
方法来“处理”事件,结果表明,该方法的性能比订阅事件要好一些。即使您认为您永远不会覆盖
OnEventName
方法,但还是要养成这样做的习惯,因为它简化了事件引发过程

以下是我们的
OnLabelsTextChanged

protected virtual void OnLabelsTextChanged(EventArgs e)
{
    EventHandler handler = this.LabelsTextChanged;
    if (handler != null)
    {
        handler(this, e);
    }
}
我们必须检查null,因为没有订阅者的事件是null。如果我们试图引发一个null事件,我们将得到一个
NullReferenceException
。请注意,在检查事件的
EventHandler
是否为null并引发事件之前,我们将其复制到一个局部变量。如果我们改为这样做:

public void LabelTextChanged(object sender,EventArgs e)
{
if(TextOfLabelChanged!=null)
TextOfLabelChanged(sender,e);
}
_myLabel.TextChanged+=LabelTextChanged;
if (this.LabelsTextChanged != null)
{
    this.LabelsTextChanged(this, e);
}
在空性检查和事件引发之间会有一个竞争条件。如果事件的订阅者恰好在我们引发事件之前取消了订阅,但在我们检查null之后,就会抛出异常。您通常不会遇到此问题,但最好养成以安全方式编写的习惯

编辑:以下是如何更改
公共事件事件处理程序标签的文本行应放置在:

namespace YourNamespace
{
    class MyUserControl : UserControl
    {
        // it needs to be here:
        public event EventHandler LabelsTextChanged;

        ...
    }
}

是关于事件设计的框架设计指南供进一步阅读。

编译错误,第二行写着:“预期的类、委托、枚举、接口或结构”,它似乎与“事件


这两行需要在类声明中

public delegate void TextChangedEventHandler(object sender, EventArgs e);
public event TextChangedEventHandler LabelTextChanged;

您必须在
命名空间
中声明
事件
委托
。请尝试将代码置于
范围内。它将正常运行。

有一种非常简单的方法可以做到这一点

在UserControl窗体上:

  • 将属性更改为public以访问所有位置
  • 在使用UserControl的主窗体上:

    .5:在
    使用
    区域中,添加
    使用userControl1=UserControl.userControl1

    1.将“Laod”事件添加到用户控件:

    this.userControl1.Load += new System.EventHandler(this.userControl1_Load);
    
    2.在userControl1_加载中:

    private void userControl1_Load(object sender, EventArgs e)
    {
         (sender as UserControl1).label1.TextChanged += label1_TextChanged; 
         //add a 'TextChanged' event to the label1 of UserControl1 
         OR use direct cast:
         ((UserControl1) sender).label1.TextChanged += label1_TextChanged;
    
    }
    
    3.在标签1_文本中更改:

     private void label1_TextChanged(object sender, EventArgs e)
     {
         //do whatever you want
     }
    

    您使用的是Winforms还是WPF?我不知道,我使用的是UserControl,但不是WPFW为什么使用“if(TextOfLabelChanged!=null)”?它有一个编译错误,wihch说:“预期的类、委托、枚举、接口或结构“一开始line@saeed:我们必须检查null,因为没有订阅服务器的事件为null。如果我们试图引发一个空事件,我们会得到一个
    NullReferenceException
    .tnx,那么编译错误呢?它有一个编译错误,wihch说:“预期的类、委托、枚举、接口或结构”在第二行,它似乎与“事件”有问题。你的想法也有同样的问题,编译器说:
    第一行的“预期类、委托、枚举、接口或结构”有问题event@saeed:您将
    公共事件事件处理程序标签放置在何处更改;
    ?它必须位于类内部(而不是方法内部或类定义外部)。@ZachJohnson非常有用!这是“继承内容所需的关键字,或者在这种情况下是可选的?您可以缩短对null
    this.ElementChanged?.Invoke(this,e)的检查时间