3

私はフォームを構築しており、いくつかのnumericUpDownコントロール、いくつかのチェックボックスコントロール、いくつかのテキストボックスなどがあります。各コントロールには、何かを実行するトリガーされるイベントメソッド(CheckedChanged、ValueChangedなど)がありますが、私の主な質問はこれです:

私がやりたいことは、フォームのテキスト フィールドを更新する単一のメソッドを実行することですが、現在は 24 回繰り返しています。これは機能しますが、もっと良い方法があるに違いないと感じています...以下は、これまでの例です。

    private void button3_Click(object sender, EventArgs e)
    {
    // Code Specific to the Buton3_Click
    UpdateTextLabel();
    }
    private void checkBox1_CheckedChanged(object sender, EventArgs e)
    {
    // Code Specific to the checkBox1_CheckChanged
    UpdateTextLabel();
    }
    private void numericUpDown1_ValueChanged(object sender, EventArgs e)
    {
    // numericUpDown1 specific code ....
    UpdateTextLabel();
    }
    private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
    {
    // comboBox1 specific stuff ...
    UpdateTextLabel();
    }
   // .... and so on for every method ....

これを達成するためのより良い方法はありますか?「コントロールがクリックまたは変更された場合...これを「UpdateTextLabel()」のように実行してください」と言いたいのですが、どうすればよいかわかりません。私が検索に入力した質問が「正しい質問」ではないようだったので、答えに導かれてうれしいです...

ありがとう!

4

3 に答える 3

2

確かに!ラムダを使用して、未使用の引数を簡単に処理できます。

button3.Click += (sender, args) => UpdateTextLabel();
checkBox1.CheckedChanged += (sender, args) => UpdateTextLabel();
numericUpDown1.ValueChanged += (sender, args) => UpdateTextLabel();
comboBox1.SelectedIndexChanged += (sender, args) => UpdateTextLabel();

または、一部の開発者が流行しているように、引数を気にしない場合は、読みやすくするためにアンダースコアを使用してそれらを「無視」できます。

button3.Click += (_, __) => UpdateTextLabel();
checkBox1.CheckedChanged += (_, __) => UpdateTextLabel();
numericUpDown1.ValueChanged += (_, __) => UpdateTextLabel();
comboBox1.SelectedIndexChanged += (_, __) => UpdateTextLabel();

強力な Jon Skeet がかつて私に教えてくれたように、これは CONTROLNAME_EVENTNAME のデフォルトの Visual Studio 命名スキームよりもはるかに優れています。テキストラベル」。また、コード ファイルが解放され、不要なメソッド ラッパーが大量に削除されます。:)

編集: 24 回繰り返すと、設計の観点からは少し奇妙に思えます。...もう一度読みますコメントを見逃しました。特定のコードを実行し、テキスト ボックスを更新したいと考えています。複数のイベントを登録できます。

button3.Click += (_, __) => SubmitForm();
button3.Click += (_, __) => UpdateTextLabel();

これに関する問題は、技術的には、イベントリスナーが順番どおりに起動することが保証されていないことです。ただし、この単純なケース (特に、イベント ハンドラーを使用したり組み合わせたりしない場合-=) では、実行順序を維持しても問題ありません。(私はあなたがUpdateTextLabelに発砲する必要があると仮定しています) SubmitForm

UpdateTextLabelまたは、呼び出しをボタン ハンドラーに移動することもできます。

button3.Click += (_, __) => SubmitForm();

private void SubmitForm(object sender, EventArgs e)
{
    //do submission stuff
    UpdateTextLabel();
}

どちらがあなたを同じボートに入れますか(メソッドの命名はより良いですが)。UpdateTextLabelおそらく代わりに、フォームの一般的な「再バインド」に移動する必要があります。

button3.Click += (_, __) => SubmitForm();

private void SubmitForm(object sender, EventArgs e)
{
    //do submission stuff
    Rebind();
}

private void Rebind()
{
    GatherInfo();
    UpdateTextLabel();
    UpdateTitles();
}

このようにして、テキスト ラベルを更新する以外に追加の作業を行う必要がある場合、すべてのコードがジェネラルRebind(または任意の名前) を呼び出し、更新が容易になります。

EDITx2: もう 1 つのオプションは、アスペクト指向プログラミングを使用することです。PostSharpのようなものを使用すると、コンパイルされる特別なコードを実行するメソッドを装飾できます。PostSharp でイベントにアタッチできると 99% 確信しています (ただし、具体的に行ったことはありません)。

button3.Click += (_, __) => SubmitForm();

[RebindForm]
private void SubmitForm(object sender, EventArgs e)
{
    //do submission stuff
}

[Serializable]
public class RebindFormAttribute : OnMethodBoundaryAspect
{
    public override void OnSuccess( MethodExecutionArgs args )
    {
        MyForm form = args.InstanceTarget as MyForm; //I actually forgot the "InstanceTarget" syntax off the top of my head, but something like that is there
        if (form != null)
        {
            form.Rebind();
        }
    }
}

したがって、どこでも明示的に呼び出しを行わなくてもRebind()、属性とアスペクト指向プログラミングはOnSuccess、メソッドが正常に呼び出されるたびに、そこで追加のコードを実行することになります。

于 2012-07-02T12:41:23.243 に答える
2

はい、イベント ハンドラー デリゲートが同じである限り、任意のコントロールのイベントは同じイベント ハンドラー メソッドを共有できます。この場合、これらのコントロールのイベント ハンドラー デリゲートはすべて「EventHandler」型です (戻り値と 2 つの引数はありません)。 : オブジェクト送信者および EventArgs e)。

private void UpdateTextLabel(object sender, EventArgs e)
{
    //your original UpdateTextLabel code here
}

button3.Click += UpdateTextLabel;
checkBox1.CheckedChanged += UpdateTextLabel;
numericUpDown1.ValueChanged += UpdateTextLabel;
comboBox1.SelectedIndexChanged += UpdateTextLabel;
于 2012-07-02T12:57:45.987 に答える
0

はい、このようなコードを書きたくありません。必要はありません。Application.Idle イベントは、UI の状態を更新するのに理想的です。Winforms が保留中のすべてのメッセージをメッセージ キューから取得した後、毎回実行されます。そのため、現在サブスクライブしているイベントの後に実行されることが保証されています。次のようにします。

    public Form1() {
        InitializeComponent();
        Application.Idle += UpdateTextLabel;
        this.FormClosed += delegate { Application.Idle -= UpdateTextLabel; };
    }

    void UpdateTextLabel(object sender, EventArgs e) {
        // etc..
    }
于 2012-07-02T12:54:40.317 に答える