web-dev-qa-db-ja.com

イベントをメソッドに渡す方法は?

イベントを引数として取り、それに適切に処理するためにeventHandlerを追加するメソッドを作成したいと思います。このような:

私には2つのイベントがあります。

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」は、+ =または-=の左側にのみ表示できます

25

私の元の回答は、イベントを定義したクラス内から適切でしたが、定義クラスの外部からこれを達成したいことを反映するように質問を更新したので、私はそれをしました。

イベントを定義するクラスだけが、イベントが使用する暗黙のデリゲート変数を参照できます。そのクラスの外からは、+=および-=を介して、addおよびremoveメソッドにのみアクセスできます。つまり、自分が求めていることを直接行うことはできません。ただし、機能的なアプローチを使用できます。

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();
    }
}
26
P Daddy

私はそれをこのようにしました:

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

アドバイスありがとうございます。この解決策は、あなたの助けなしでは実現できませんでした。

6

書くだけ tool.Click += Item_Click;

編集:MSDNから「イベントは、それらが宣言されているクラスまたは構造内からのみ呼び出すことができます」。だからあなたがしようとしていることは不可能です。あなたのニーズについてもっと詳しく教えてもらえますか?なぜイベントをパラメーターとして渡したいのですか?

2
Petar Minchev

不可能です。必要に応じて、イベントの代わりにデリゲートを使用できます。

2
Jamie Ide
    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);
    }
1
thelost

あなたの質問は、いくつかのメカニズムが間違っていることを示唆しています:イベントを渡すことはできません!

ほとんどの場合、関数をパラメーターとして渡したいので、呼び出し元のメソッドは、ある時点で他のメソッドを呼び出します。専門用語では、これはデリゲートです。すでに定義されているActionクラスを使用することをお勧めします。以下はスニペットの例です。

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

これの良い点は、MyFunctionを呼び出すときに、インライン構文を使用してアクションを宣言できることです。

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

次のように(イベントの代わりに)関数/メソッドを渡します。

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();
    }
}
0
T.Todua