区分附加到同一事件处理程序的多个对象

本文关键字:程序 对象 事件处理 | 更新日期: 2023-09-27 18:27:39

我很难弄清楚如何搜索/表达我想要实现的目标。我想看看是否有更安全/更聪明的方法来实现以下示例。

假设我有3个带名称的按钮:

b一个
btnTwo
btnThree

每个按钮的目的是在单击时向某个文本框写入一个唯一的字符串。由于所有三个按钮都执行非常相似的操作,因此为所有三个创建一个事件处理程序似乎是合乎逻辑的,但区分这三个按钮以使正确的文本框能够获得正确的字符串的明智方法是什么?我不喜欢目前的做法:

伪,伪代码:

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;
    }
}

另一种方法是为每个按钮都有一个点击事件处理程序,然后有一个常见的方法,比如:

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

区分附加到同一事件处理程序的多个对象

在您的情况下,重用的代码将some文本框的Text属性设置为somestring。就我个人而言,我看不出以您为演示的操作演示的方式编写单个事件处理程序有什么好处。IMHO它使代码复杂化而不是简化

最好有三个独立的处理程序,将三个独立文本框属性设置为三个独立字符串。然后,您就不需要做任何进一步的比较来找出是哪个按钮发送了事件。

根据实际应用程序和处理程序内部的代码,此观察结果可能有效,也可能无效。


然而,可以重构它的一种方法是:

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];
}

第二种方法是使用每个按钮的Tag属性。我喜欢这个,因为它把所有的东西都封装在按钮中。然而,缺点是只有一个Tag属性,并且不能保证它包含适当的信息。(您也可以将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;
}

这是一个非常简单的情况,为了简单起见,我想我应该把它们都放在自己的事件处理程序中。

如果你想有一个事件,你可以使用:测试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";
}

至少,如果你重命名按钮,你的程序将不会编译,你会来这里修复它

按照现在的方式,如果将"btOne"重命名为"btn1",tbOne中的文本将无法更新,您可能不会注意到它。