如何在C#中手动调用事件?

时间:2010-10-01 16:32:43

标签: c# winforms visual-studio-2010

我有一个USerControll,我有一个文本框。我在表单中使用usercontrol,当有人在文本框中按Enter键时我想做某事。我该怎么做? 如果你告诉我如何手动调用事件,我可以在textbox.keydown中调用usercontrol.keydown。

6 个答案:

答案 0 :(得分:12)

首先,只能从声明事件的控件中的代码引发事件。因此,您的用户控件必须声明自定义事件KeyDown才能引发它。例如,您不能在用户控件包含的TextBox上引发KeyDown。但是,您可以声明自己的KeyDown,并将一个处理程序附加到TextBox的KeyDown,它将引发您自己的KeyDown。

鉴于此限制,举办活动很容易:

public delegate void MyEventHandler(object sender, MyEventArgs e)

public event MyEventHandler MyEvent;

public void RaisesMyEvent()
{
   ...

   if(MyEvent != null) //required in C# to ensure a handler is attached
      MyEvent(this, new MyEventArgs(/*any info you want handlers to have*/));
}

举起一个事件看起来很像一个方法,因为从本质上讲,这就是你正在做的事情;您正在调用在事件幕后分配给MultiCast委托的一个或多个方法委托。可以把它想象成为一个普通的命名委托分配一个方法(比如你从定义中省略了“event”关键字)并从你的代码中调用它。 true事件与事件之间的唯一区别是事件可以附加多个处理程序委托,并在引发时调用所有事件。

答案 1 :(得分:3)

我正在寻找这个问题的答案,

就这样做

examble:

//this is the call to trigger the event:

 **lst_ListaDirectorios_SelectedIndexChanged(this, new EventArgs());**

//do that if you have the method signature in the same class as I do. (something like this below)
private void lst_ListaDirectorios_SelectedIndexChanged(object sender, EventArgs e)
        {
          //do something
         }

我希望这对你有用。

答案 2 :(得分:1)

通常,事件调用包含在名为“On [EventName]”的方法中,该方法验证delgate是否有一个或多个目标(事件不为空),然后使用发送方和任何适用的参数调用它......所以像这样的典型模式:

public event EventHandler SomethingHappened;
protected void OnSomethingHappend(EventArgs e)
{
    if (SomethingHappened != null)
        SomethingHappened(this, e);
}

任何需要引发该事件的事件都会调用该方法(假设它是可访问的)。

如果你只想传递事件,那么作为UserControl,你可能只是调用可能暴露的基础“On [Event]”方法。您也可以连接事件处理程序,直接将子控件中的事件作为父控件的事件传递...以便txtFoo.KeyPress只调用父控件的OnKeyPress方法。

答案 3 :(得分:0)

您所描述的内容称为事件冒泡。这是一个例子:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MyUserControl.ascx.cs" Inherits="MyUserControl" %>

<asp:TextBox ID="TextBox1" runat="server" OnTextChanged="TextBox1_TextChanged" />

public partial class MyUserControl : UserControl
{
 public event EventHandler UserControlTextBoxChanged;

 protected void TextBox1_TextChanged(object sender, EventArgs e) {
  if (UserControlTextBoxChanged != null)
   UserControlTextBoxChanged(sender, e);
 }
}

<%@ Page Language="C#" AutoEventWireup="True" Inherits="Default" CodeBehind="Default.aspx.cs" %>
<%@ Register Src="~/MyUserControl.ascx" TagName="MyUserControl" TagPrefix="uc1" %>

<uc1:MyUserControl ID="ucMyUserControl" runat="server" OnUserControlTextBoxChanged="ucMyUserControl_UserControlTextBoxChanged" />

public partial class MyPage : Page {
 protected void ucMyUserControl_UserControlTextBoxChanged(object sender, EventArgs e) {
  // sender is ucMyUserControl.TextBox1
 }
}

答案 4 :(得分:0)

如果您使用的是WPF,则可以使用RaiseEvent:http://msdn.microsoft.com/en-us/library/system.windows.uielement.raiseevent.aspx

但这对你想做的事情是错误的。

你应该为这个事件起泡。

class MyControl : UserControl {
    public KeyDownEventHandler KeyDown;

    private void OnTextBoxKeyDown(object sender, EventArgs e){ KeyDown.Invoke(sender, e); }
}

然后从表单中收听KeyDown。请原谅各种元素/事件的命名错误。

答案 5 :(得分:-1)

如果您真的需要手动调用事件,则可以获取通常是私有的后备委托。使用.NET反编译器(例如ILSPY)找到事件的后备字段,然后使用反射来获取后备委托。

示例:从DoWork获取事件BackgroundWorker

在ILSpy中反编译BackgroundWorker类,您会看到以下内容:

public event DoWorkEventHandler DoWork
{
    add
    {
        base.Events.AddHandler(doWorkKey, value);
    }
    remove
    {
        base.Events.RemoveHandler(doWorkKey, value);
    }
}

因此,您需要找到Events成员,并将doWorkKey字段作为键。

Events是在类EventHandlerList中声明的Component(公共类)。

doWorkKey是在类BackgroundWorker中声明的静态字段。

然后使用反射来获取委托:

PropertyInfo property = backgroundWorker.GetType().GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
EventHandlerList eventHandlerList = (EventHandlerList)property.GetValue(backgroundWorker, null);
FieldInfo doWorkField = backgroundWorker.GetType().GetField("doWorkKey", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy);
object doWorkKey = doWorkField.GetValue(null);
DoWorkEventHandler doWork = (DoWorkEventHandler)eventHandlerList[doWorkKey];

现在您有一个DoWork事件的委托人,可以调用它。

同样的方法也适用于其他控件。

请注意,只要有新版本的代码,使用反射来获取私有字段可能会中断。