2011-11-18 6 views
6

ウィンドウのすべての検証ロジックを含む関数void Validate()があります。異なるイベントハンドラデリゲートを持つ複数のコントロール用に単一のイベントハンドラを実装する

イベントハンドラデリゲートが必要とするパラメータを受け入れないため、単にイベントハンドラとして登録することはできません。さらに、異なるタイプのコントロールには異なるシグネチャがあるため、内容を無視してValidateのシグネチャと一致させることはできません。ここで

は、私がセットアップ

txt1.TextChanged += Validate_TextChange; 
    password1.PasswordChanged += Validate_RoutedEvent; 
    txt2.TextChanged += Validate_TextChange; 

    txt3.TextChanged += Validate_TextChange; 
    password2.PasswordChanged += Validate_RoutedEvent; 
    txt4.TextChanged += Validate_TextChange; 


void Validate_RoutedEvent(object sender, RoutedEventArgs e) 
{ 
    ValidateOptions(); 
} 

void Validate_TextChange(object sender, TextChangedEventArgs e) 
{ 
    ValidateOptions(); 
} 

public void ValidateOptions() 
{ 
    //Actual validation here 
} 

これはわずか2例を示したもの、より多くのコントロールがさらに署名を持つことができるの小さな例です。渡された引数が気にしない場合に、すべてのイベントハンドラが関数を呼び出すより良い方法はありますか?


EDIT: 私はパラメータを追加し、単にそれらを無視するジョンによって提案されたオプションが好きです。それは問題のほとんどを解決しますが、手動で検証をトリガするなど、この関数を直接呼び出す場合はいつでも、コンパイラを満たすために仮引数を含める必要があります。 ValidateOptions(this、new EventArgs())

Danは、匿名関数を使用するようにしましたが、これを処理しますが、イベントハンドラを関連付けるときはきれいではありません。

どちらの解決策でも、シグネチャを無視している間にイベントハンドラとして関数を登録できますが、仮引数を作成せずに関数を呼び出すことはできますが、かなり近づく方法は複数あります。


編集:ここでは

あなたが減らすために、ラムダ式を使用することができます直接

txt1.TextChanged += ValidationEvent; 
password1.PasswordChanged += ValidationEvent; 
txt2.TextChanged += ValidationEvent; 

txt3.TextChanged += ValidationEvent; 
password2.PasswordChanged += ValidationEvent; 
txt4.TextChanged += ValidationEvent; 


//Single event handler accepting EventArgs, which is the base class 
//for all more-specific event classes 
void ValidationEvent(object sender, EventArgs e) 
{ 
    //Ignores arguments and calls 0 argument ValidateOptions 
    ValidateOptions(); 
} 

//0 argument function that performs actual validation and can be called 
//directly from other functions without the need to pass in a fake sender 
//and eventargs parameter 
public void ValidateOptions() 
{ 
    //Actual validation here 
} 

答えて

6

あなたはパラメータを無視し、単一のメソッドを持つことができます第1のパラメータはsenderであり、第2のパラメータはEventArgsから派生したいくつかのタイプであることを示している。

+0

がさえ署名 '無効(オブジェクト、オブジェクト)'実際に働くだろう...消費のために保存されます。 –

+2

@ H.B。:True - 私はそれがイベント処理のためにそこにあることを明白にすることを好むでしょう:) –

+0

@Jon私はこれが好きで、うまくいったが、私は私のオリジナルの質問(ユースケース) 。 Validate()関数がまだこれをしていない理由の1つは、他の関数から検証を強制するために呼び出すためです。このアプローチでは、イベントハンドラの使用を簡略化しますが、直接呼び出すときは偽の値を使用する必要があります。 – Eric

5

呼び出すことができます0パラメータ機能を扱うが、維持する一般的なイベントのためのJonのソリューションを実装する更新例です。ラッパーのために書くコードの量は、舞台裏ではまだ、パラメータを破棄するためのラッパーメソッドを作成しています。通常のイベントの模様などに以下のコンパイラがどのデリゲート型からValidateOptions方法グループからの変換が可能になります

public void ValidateOptions(object sender, EventArgs e) 
{ 
} 

txt3.TextChanged += (s,e) => ValidateOptions(); 
password2.PasswordChanged += (s,e) => ValidateOptions(); 
txt4.TextChanged += (s,e) => ValidateOptions(); 
0

このハンドラは、フレームワークコントロールのための単一のコールバックを提供し、引数「E」の

private static void EventHandlerSink(object sender, dynamic e) 
    { 

    } 
+0

すべてのイベント引数が 'EventArgs'から継承するときに' dynamic'を使う必要はありません。ボクシングするときに残しておいた小さなインターフェースを緩めるだけです。 –

関連する問題