たとえば、イベントハンドラーを割り当てるときに追加のデータを渡したいとします。次のコードを検討してください。
private void setup(string someData)
{
Object.assignHandler(evHandler);
}
public void evHandler(Object sender)
{
// need someData here!!!
}
EvHandlerメソッドにsomeDataを取得するにはどうすればよいですか?
private void setup(string someData)
{
Object.assignHandler((sender) => evHandler(sender,someData));
}
public void evHandler(Object sender, string someData)
{
// need someData here!!!
}
上記の@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
オブジェクトを含むスレッドセーフでない例外は例外です。この例外は、サンプルの動作方法を変更するとは思わない)。私は今それを理解しています。
キャプチャされた変数:
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);
});
これを試してみることができます:
string yourObject;
theClassWithTheEvent.myEvent += (sender, model) =>
{
yourObject = "somthing";
}
類似した私の質問は重複しているとマークされていたので、質問に答えさせないので、ここに答えを追加すると思いました。
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);
}
}
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;
}
初期化後にデータを変更しない場合は、たとえば、カスタムコンストラクターを追加することもできます。
さて、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の方法であるかどうかはわかりませんが、実際にはイベントの種類、オブジェクトなどに依存します。
追加のパラメーターをタイマーハンドラーに渡す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));
}