2

達成しようとしていることを検索/フレーズ化する方法を理解するのに苦労しました。次の例を実現するためのより安全でスマートな方法があるかどうかを調べています。

名前の付いた 3 つのボタンがあるとします:

btnOne
btnTwo
btnThree

各ボタンの目的は、クリックされたときに特定のテキスト ボックスに一意の文字列を書き込むことです。3 つのボタンはすべて非常によく似たアクションを実行するため、3 つすべてに使用する 1 つのイベント ハンドラーを作成するのは理にかなっていますが、適切なテキスト ボックスが正しい文字列を取得できるように、3 つのボタンを区別するスマートな方法は何でしょうか? 私はそれについて行っている現在の方法が好きではありません:

疑似、疑似コード:

private void Clicked(object sender, EventArgs e)
{
    string buttonName = (sender as Button).Name;
    switch(buttonName)
    {
         case "btnOne":
             tbOne.Text = "This text is from button one";
             break;
         case "btnTwo":
             tbTwo.Text = "This is some different text";
             break;
         case "btnThree":
             tbThree.Text = "Button three text";
             break;
    }
}

もう 1 つの方法は、次のような一般的なメソッドを持つ各ボタンのクリック時イベント ハンドラーを用意することです。

private void AfterButtonClicked(Textbox tb, string text)
{
    tb.Text = text;
}
4

2 に答える 2

1

あなたの場合、再利用されたコードは、テキストボックスのプロパティを文字列に設定Textます個人的には、あなたが実演したアクションに対して実演した方法で単一のイベントハンドラーを書くことの利点はわかりません。私見では、コードを単純化するのではなく、コードを複雑にします。

3 つの個別のテキスト ボックス プロパティを 3 つの個別の文字列に設定する 3 つの個別のハンドラーを用意することをお勧めします。そうすれば、どのボタンがイベントを送信したかを調べるために、それ以上の比較を行う必要がなくなります。

実際のアプリケーションとハンドラー内のコードに応じて、この観察が有効な場合と無効な場合があります。


ただし、これをリファクタリングできる1 つの方法は次のとおりです。

Dictionary<Button, TextBox> buttonTextboxMap = new Dictionary<Button, TextBox> 
{
    {btnOne, tbOne}, 
    {btnTwo, tbTwo}, 
    {btnThree, tbThree}
};

Dictionary<Button, string> buttonStringMap = new Dictionary<Button, string> 
{
    {btnOne, "This text is from button one"},
    {btnTwo, "This is some different text"},
    {btnThree, "Button three text"}
};

void Clicked(object sender, EventArgs e)
{
    Button btn = (Button)sender;

    buttonTextboxMap[btn].Text = buttonStringMap[btn];
}

2 番目の方法は、各ボタンのTagプロパティを使用することです。ボタン自体にすべてがカプセル化されているため、これが気に入っています。ただし、Tagプロパティが 1 つしかなく、適切な情報が保持されているとは限りません。(適切な情報を保持するようにサブクラス化することもできますがButton、それは、どれだけの再利用性を求めているか、この特定のボタンを何回使用するかに依存すると思います):

class TextBoxAndString
{
    public TextBox tb {get; set;}
    public String s {get; set;}
}

.ctor() //the form's constructor
{
    btnOne.Tag = new TextBoxAndString {tb = tbOne, s = "This text is from button one"};
    btnTwo.Tag = new TextBoxAndString {tb = tbTwo, s = "This is some different text"};
    btnThree.Tag = new TextBoxAndString {tb = tbThree, s = "Button three text"};   
} 

void Clicked(object sender, EventArgs e)
{
    Button btn = (Button)sender;
    TextBoxAndString tbs = (TextBoxAndString)btn.Tag;

    tbs.tb.Text = tbs.s;
}
于 2013-08-15T02:34:16.110 に答える
0

これは非常に単純なケースです。単純にするために、すべてを独自のイベント ハンドラーに残しておくことにします。

ただし、1 つのイベントが必要な場合は、次senderを使用してテストできます。

private void Clicked(object sender, EventArgs e)
{
    if (sender is btnOne)
        tbOne.Text = "This text is from button one";
    else if (sender is btnTwo)
        tbTwo.Text = "This is some different text";
    else if (sender is btnThree)
         tbThree.Text = "Button three text";
}

少なくとも、ボタンの名前を変更すると、プログラムはコンパイルされないので、修正するためにここに来ます。

現在の方法では、「btnOne」を「btn1」に名前変更すると、テキストのtbOne更新に失敗し、気付かない場合があります。

于 2013-08-15T02:29:21.730 に答える