如何将事件传递给方法?

时间:2010-04-01 12:27:01

标签: c# events event-handling delegates

我想创建一个方法,将事件作为参数,并向其添加eventHandler以正确处理它。像这样:

我有两件事:

public event EventHandler Click;
public event EventHandler Click2;

现在我想将特定事件传递给我的方法(伪代码):

public AttachToHandleEvent(EventHandler MyEvent)
{
    MyEvent += Item_Click;
}

private void Item_Click(object sender, EventArgs e)
{
    MessageBox.Show("lalala");
}

ToolStripMenuItem tool = new ToolStripMenuItem();
AttachToHandleEvent(tool.Click);

有可能吗?

我注意到这段代码工作正常,并返回到我的项目,并注意到当我传递在我的类中声明的事件时,它可以工作,但是当我从其他类传递事件时它仍然无效。

我得到的是这个错误:

  

活动   'System.Windows.Forms.ToolStripItem.Click'   只能出现在左侧   + =或 - =

8 个答案:

答案 0 :(得分:24)

我的原始答案适用于定义该事件的类中,但您已经更新了您的问题,以反映您希望从定义类之外完成此操作,所以我已经打败了它。

只有定义事件的类才能引用事件使用的隐式委托变量。在该课程之外,您只能通过addremove访问+=-=方法。这意味着你不能直接做你所要求的。但是,您可以使用功能方法。

class A{
    public event EventHandler Event1;

    public void TriggerEvent1(){
        if(Event1 != null)
            Event1(this, EventArgs.Empty);
    }
}

class B{
    static void HandleEvent(object o, EventArgs e){
        Console.WriteLine("Woo-hoo!");
    }

    static void AttachToEvent(Action<EventHandler> attach){
        attach(HandleEvent);
    }

    static void Main(){
        A a = new A();
        AttachToEvent(handler=>a.Event1 += handler);
        a.TriggerEvent1();
    }
}

答案 1 :(得分:5)

我是这样做的:

public AttachToHandleEvent(Object obj, string EventName)
{
    EventInfo mfi = obj.GetType().GetEvent(EventName);
    MethodInfo mobj = mfi.GetAddMethod();
    mobj.Invoke(obj, new object[] { Item_Click});
}

private void Item_Click(object sender, EventArgs e)
{
    MessageBox.Show("lalala");
}

ToolStripMenuItem tool = new ToolStripMenuItem();
AttachToHandleEvent(tool "Click");

谢谢大家的建议。没有你的帮助,这个解决方案无法完成。

答案 2 :(得分:2)

只需撰写tool.Click += Item_Click;

即可

编辑:来自MSDN“只能从声明它们(它)的类或结构中调用事件”。所以你要做的就是不可能。你能详细说明你的需求吗?为什么要将事件作为参数传递?

答案 3 :(得分:2)

这是不可能的。如果符合您的需要,您可以使用代理而不是事件。

答案 4 :(得分:1)

    delegate void doIt(object sender, object data);
    event doIt OnDoIt;

    void add(doIt theDel)
    {
        OnDoIt += theDel;
    }

    void doIt1(object a, object b)
    {
    }

    void doIt2(object a, object b)
    {
    }

    void add()
    {
        add(doIt1);
        add(doIt2);
    }

答案 5 :(得分:0)

你的问题表明你有一些错误的机制: 你无法通过活动!

您最有可能希望将函数作为参数传递,因此调用方法将在某个时刻调用其他方法。在技​​术方面,这是一个代表。我建议使用已定义的Action类。这是一个示例代码段:

void MyFunction (string otherArguments, Action onFinished){
    ...
    if (onFinished != null)
        onFinished.Invoke();
}

关于这一点的好处是,在调用MyFunction时,您可以使用内联语法声明Action:

MyFunction("my other argument", ()=>{
    ///do stuff here, which will be execuded when the action is invoked
});

答案 6 :(得分:0)

我这样传递函数/方法(而不是事件):

class A
{
    public void something()
    {
        var myAction = 
            new Action<object, object>((sender, evArgs) => {
                MessageBox.Show("hiii, event happens " + (evArgs as  as System.Timers.ElapsedEventArgs).SignalTime); 
            });
        B.timer(myAction);
    }
}

class B
{
    public static void timer( Action<object, System.Timers.ElapsedEventArgs> anyMethod)
    {
        System.Timers.Timer myTimer = new System.Timers.Timer();
        myTimer.Elapsed += new System.Timers.ElapsedEventHandler(anyMethod);
        myTimer.Interval = 2000;
        myTimer.Start();
    }
}

答案 7 :(得分:0)

使用面向对象的解决方案更新此问题。

您可以创建一个为您处理的对象,而不是使用 Action<EventHandler> 来注册事件

    public class AEvent
    {
        private readonly A aInstance;
        private AEvent(A instance) {
            aInstance = instance;
        }        

        public void Add(EventHandler eventHandler)
            => a.Event1 += eventHandler;

        public void Remove(EventHandler eventHandler)
            => a.Event1 -= eventHandler;

        public EventHandler Invoke => aInstance.Event1;
    }

然后像这样使用该对象:

    static void Main(){
        A a = new A();
        AEvent aEvent = new AEvent(A)
        aEvent.Add(handler);
        a.Invoke();
    }