开发者

How to call an event manually in C#?

I have a USerControll in which i have a textbox. I use the usercontrol in my form, I want to do something when somebody presses enter on the textbox. how can I do it? if you t开发者_如何转开发ell me how to call an event manually, I can call usercontrol.keydown in textbox.keydown.


First, events can only be raised from code within the control that declares the event. So, your user control has to declare the custom event KeyDown in order to raise it. You cannot, for instance, raise KeyDown on a TextBox contained by your user control. However, you can declare your own KeyDown, and attach a handler to the TextBox's KeyDown that will raise your own KeyDown.

Given this restriction, raising an event is easy:

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

Raising an event looks much like a method, because in essence that's what you're doing; you're calling one or more method delegates that are assigned to the MultiCast delegate behind the scenes of your event. Think of it as assigning a method to an ordinary named delegate (like if you'd omitted the "event" keyword from the definition) and calling it from inside your code. the only difference between a true event and that is that an event can have more than one handler delegate attached to it, and will invoke all of them when raised.


I was looking for an answer to this issue for me,

just do this

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
         }

I hope this was useful for you.


Typically, the event invokation is wrapped in a method named something like "On[EventName]" which validates that the delgate has one or more targets (event is not null), and then invokes it with the sender and any applicable arguments...so something like this is the typical pattern:

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

Anything that needs to raise that event invokes that method (assuming its accessible).

If you simply want to pass the event along, then as a UserControl, you can probably just invoke the base "On[Event]" method, which is likely exposed. You can wire up the event handlers, too, to directly pass the event from a child control as the event of the parent control...so that txtFoo.KeyPress simply invokes the OnKeyPress method of the parent control.


What you describe is called event bubbling. Here's an example:

<%@ 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
 }
}


If you are using WPF, you might be able to use RaiseEvent: http://msdn.microsoft.com/en-us/library/system.windows.uielement.raiseevent.aspx

But this is wrong for what you want to do.

You should bubble the event.

class MyControl : UserControl {
    public KeyDownEventHandler KeyDown;

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

Then listen to KeyDown from your form. Please excuse mistakes in the naming of the various elements / events.


If you REALLY need to call an event manually, you can get the backing delegate, which is usually private. Use a .NET decompiler (such as ILSPY) to locate the Event's backing field, then use reflection to get the backing delegate.

Example: Getting the event DoWork from BackgroundWorker:

Decompile the BackgroundWorker class in ILSpy, and you see this:

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

So you need to find the Events member, and the doWorkKey field as a key.

Events is an EventHandlerList (public class) declared in class Component.

doWorkKey is a static field declared in class BackgroundWorker.

Then use reflection to get the delegate:

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];

Now you have a delegate for the DoWork event, and can call it.

This same approach will also work for other Controls.

Note that using reflection to get private fields may break any time there is a new version of the code.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜