web-dev-qa-db-ja.com

C#はイベントハンドラに余分なパラメータを渡しますか?

たとえば、イベントハンドラーを割り当てるときに追加のデータを渡したいとします。次のコードを検討してください。

private void setup(string someData)
{
     Object.assignHandler(evHandler);
}

public void evHandler(Object sender)
{
    // need someData here!!!
}

EvHandlerメソッドにsomeDataを取得するにはどうすればよいですか?

55
Andy Hin
private void setup(string someData)
{
     Object.assignHandler((sender) => evHandler(sender,someData));
}
public void evHandler(Object sender, string someData)
{
    // need someData here!!!
}
51
spender

上記の@spenderの例を特に理解するのに苦労しました:Object.assignHandler((sender) => evHandler(sender,someData));文字通りの意味でObject.assignHandlerのようなものはないので。だから私はもう少しグーグルをして、 この例 を見つけました。 Peter Dunihoの答えは私の頭をクリックしたものでした(これは私の仕事ではありません):

切り取る

通常のアプローチは、変更された署名を持つイベントハンドラーで匿名メソッドを使用することです。例えば:

void Onbutton_click(object sender, EventArgs e, int i) { ... }

button.Click += delegate(object sender, EventArgs e) 
{ Onbutton_click(sender, e, 172); };

もちろん、172を渡す必要はなく、3番目のパラメーターをintにする必要もありません。 :)

/ snip

その例を使用すると、ラムダ表記を使用して、2つのカスタムComboBoxItemオブジェクトをTimer.Elapsedイベントに渡すことができました。

simulatorTimer.Elapsed +=
(sender, e) => onTimedEvent(sender, e,
(ComboBoxItem) cbPressureSetting.SelectedItem,
(ComboBoxItem) cbTemperatureSetting.SelectedItem);

そして、そのハンドラーに:

static void onTimedEvent(object sender, EventArgs e, ComboBoxItem pressure, ComboBoxItem temperature)
    {
        Console.WriteLine("Requested pressure: {0} PSIA\nRequested temperature: {1}° C", pressure, temperature);
    }

これは上記の例の新しいコードではありませんが、それらの解釈方法を示しています。うまくいけば、私のような人がそれが有益で有益だと思うので、彼らが私のように概念を理解しようとして時間を費やすことはありません。

このコードは私のプロジェクトで動作します(ComboBoxItemオブジェクトを含むスレッドセーフでない例外は例外です。この例外は、サンプルの動作方法を変更するとは思わない)。私は今それを理解しています。

22
delliottg

キャプチャされた変数:

private void setup(string someData)
{
    Object.assignHandler((sender,args) => {
        evHandler(sender, someData);
    });
}

public void evHandler(Object sender, string someData)
{
    // use someData here
}

または(C#2.0の代替):

    Object.assignHandler((EventHandler)delegate(object sender,EventArgs args) {
        evHandler(sender, someData);
    });
18
Marc Gravell

これを試してみることができます:

string yourObject;

theClassWithTheEvent.myEvent += (sender, model) =>
{
 yourObject = "somthing";
}
3
Idan

類似した私の質問は重複しているとマークされていたので、質問に答えさせないので、ここに答えを追加すると思いました。

class Program
    {
        delegate void ComponentEventHandler(params dynamic[] args);

        event ComponentEventHandler onTest;

        static void Main(string[] args)
        {  
            Program prg = new Program();

            // can be bound to event and called that way
            prg.onTest += prg.Test;
            prg.onTest.Invoke("What", 5, 12.0);

            Console.ReadKey();
        }

        public void Test(params dynamic[] values)
        {
            // assign our params to variables
            string name = values[0];
            int age = values[1];
            double value = values[2];

            Console.WriteLine(name);
            Console.WriteLine(age);
            Console.WriteLine(value);
        }
    }
1
user441521

Objectに基づく追加のプロパティを持つカスタムオブジェクトを作成できます。

class CustomObject : Object
{
    public string SomeData;
}

private void setup(string someData)
{
    CustomObject customObject = new CustomObject { SomeData = someData };
    CustomObject.assignHandler(evHandler);
}

public void evHandler(Object sender)
{
    string someData = ((CustomObject)sender).SomeData;
}

初期化後にデータを変更しない場合は、たとえば、カスタムコンストラクターを追加することもできます。

0
Michael Geier

さて、someDataを次のようなメンバー変数にする最も簡単なメソッドID:

public class MyClass
{
    private string _eventData;

    private void setup(string someData) 
    {
       _eventData = someData;
       Object.assignHandler(evHandler);
    }

    public void evHandler()
    {
        // do something with _eventData here
    }
}

それがbestの方法であるかどうかはわかりませんが、実際にはイベントの種類、オブジェクトなどに依存します。

0
CodingGorilla

追加のパラメーターをタイマーハンドラーに渡す1行のソリューションを次に示します。

private void OnFailed(uint errorCode, string message)
{
    ThreadPoolTimer.CreateTimer((timer) => {
    UI.ErrorMessage = string.Format("Error: 0x{0:X} {1}", errorCode, message);
    }, System.TimeSpan.FromMilliseconds(100));
}
0
Ramius