简体   繁体   English

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

[英]How to add an event to a UserControl in C#?

I have a UserControl which contains 3 labels. 我有一个包含3个标签的UserControl。 I want to add an event for it, which occurs when the text of one of the labels changed. 我想为它添加一个事件,当其中一个标签的文本发生变化时会发生这种事件。
I am using Visual Studio 2010 我正在使用Visual Studio 2010

First, you need to declare the event within your class (alongside your methods and constructors): 首先,您需要在类中声明事件(与方法和构造函数一起):

public event EventHandler LabelsTextChanged;

Then you need to create a method to handle the individual labels' TextChanged events. 然后,您需要创建一个方法来处理单个标签的TextChanged事件。

private void HandleLabelTextChanged(object sender, EventArgs e)
{
    // we'll explain this in a minute
    this.OnLabelsTextChanged(EventArgs.Empty);
}

Somewhere, probably in your control's constructor, you need to subscribe to the label's TextChanged events. 某处,可能在您的控件的构造函数中,您需要订阅标签的TextChanged事件。

myLabel1.TextChanged += this.HandleLabelTextChanged;
myLabel2.TextChanged += this.HandleLabelTextChanged;
myLabel3.TextChanged += this.HandleLabelTextChanged;

Now for the HandleLabelsTextChanged method. 现在为HandleLabelsTextChanged方法。 We could raise LabelsTextChanged directly; 我们可以直接提高LabelsTextChanged ; however, the .NET framework design guidelines say that is it a best practice to create an OnEventName protected virtual method to raise the event for us. 但是,.NET框架设计指南说,最好的做法是创建一个OnEventName受保护的虚拟方法来为我们引发事件。 That way, inheriting classes can "handle" the event by overriding the OnEventName method, which turns out to have a little better performance than subscribing to the event. 这样,继承类可以通过重写OnEventName方法来“处理”事件,事实证明它比订阅事件具有更好的性能。 Even if you think you will never override the OnEventName method, it is a good idea to get in the habit of doing it anyway, as it simplifies the event raising process. 即使你认为你永远不会覆盖OnEventName方法,但最好还是养成这样做的习惯,因为它简化了事件提升过程。

Here's our OnLabelsTextChanged : 这是我们的OnLabelsTextChanged

protected virtual void OnLabelsTextChanged(EventArgs e)
{
    EventHandler handler = this.LabelsTextChanged;
    if (handler != null)
    {
        handler(this, e);
    }
}

We have to check for null because an event without subscribers is null. 我们必须检查null,因为没有订阅者的事件是null。 If we attempted to raise a null event, we would get a NullReferenceException . 如果我们尝试引发null事件,我们将得到NullReferenceException Note that we copy the event's EventHandler to a local variable before checking it for null and raising the event. 请注意,我们将事件的EventHandler复制到局部变量,然后再将其检查为null并引发事件。 If we had instead done it like this: 如果我们这样做了:

if (this.LabelsTextChanged != null)
{
    this.LabelsTextChanged(this, e);
}

We would have a race condition between the nullity check and the event raising. 我们会在无效性检查和事件提升之间存在竞争条件。 If it just so happened that the subscribers to the event unsubscribed themselves just before we raised the event but after we checked for null, an exception would be thrown. 如果碰巧事件的订阅者在我们提出事件之前取消订阅,但在我们检查了null之后,将抛出异常。 You won't normally encounter this issue, but it is best to get in the habit of writing it the safe way. 你通常不会遇到这个问题,但最好养成以安全的方式编写它的习惯。

Edit: Here is how the public event EventHandler LabelsTextChanged; 编辑:以下是public event EventHandler LabelsTextChanged; line should be placed: 应该放置一行:

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

        ...
    }
}

Here are the framework design guidelines on event design for further reading. 以下是有关事件设计的框架设计指南,供进一步阅读。

First you should declare an event in your usercontrol for example: 首先,您应该在usercontrol中声明一个事件,例如:

public event EventHandler TextOfLabelChanged;

then you have to call the call back function that is bound to your event(if there's any) in runtime.You can do this by handling the TextChanged event of a label like this: 那么你必须在运行时调用绑定到你的事件(如果有的话)的回调函数。你可以通过处理像这样的标签的TextChanged事件来做到这一点:

public void LabelTextChanged(object sender,EventArgs e)
{
if(TextOfLabelChanged!=null)
TextOfLabelChanged(sender,e);
}

You can have your own EventArgs object if you like. 如果您愿意,可以拥有自己的EventArgs对象。

somewhere in your code you should bound your label TextChanged event to this method like this: 在代码中的某处,您应该将标签TextChanged事件绑定到此方法,如下所示:

_myLabel.TextChanged+=LabelTextChanged;

There is a very simple way to do that! 有一种非常简单的方法可以做到这一点!

On the UserControl Form : 在UserControl表单上:

  1. change properties to public to access everywhere 将属性更改为public以便随处访问

on the main form , where you are using UserControl: 在主窗体上,您正在使用UserControl:

.5: in the using region add using userControl1=UserControl.userControl1 .5:在using区域添加using userControl1=UserControl.userControl1

1.Add 'Laod' event to your UserControl : 1.将'Laod'事件添加到UserControl:

this.userControl1.Load += new System.EventHandler(this.userControl1_Load);

2.In the userControl1_Load : 2.在userControl1_Load中:

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.In th label1_TextChanged: 3.在label1_TextChanged中:

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

compile error, which says: "Expected class, delegate, enum, interface, or struct" on the second line it seems to have a problem with "event... 编译错误,在第二行显示“预期的类,委托,枚举,接口或结构”,它似乎与“事件......有问题”


These 2 lines need to be INSIDE the class declaration. 这两行需要在INSIDE类声明中。

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

You must be declaring the event and delegate within the Namespace . 您必须在Namespace声明eventdelegate Try to bring the code within the class Scope. 尝试将代码放在class Scope中。 It will run fine. 它运行正常。

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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM