如何在所谓事件中找到引发事件的控件?Visual C#

6
我正在编写一个C#程序,该程序接收一系列参数并对数据点进行转换,然后将其绘制到屏幕上。
在我的一个窗体上,我有许多文本框,我希望它们都执行相同的KeyPress事件。以前,我只是用一个switch语句来处理KeyPress事件的发送者,并将其与所有文本框进行比较。但是现在我有20多个文本框,这种方法似乎不太有效率。
我想要做的是找到哪个文本框在窗体上发送了KeyPress事件,并从该文本框获取更多信息(例如其文本值等)。这样可以避免我必须使用sender进行大量判断,看它是否等于某个文本框。但是我一直无法解决这个问题。
我已经查看了System.Windows.Controls和System.Windows.Forms类,看看是否能找到任何有用的内容。我在寻找的是一些能够让我看到哪个控件获得了焦点的东西。也许那就是我应该搜索的内容?我还查看了KeyPress事件中的sender可以做什么,以便确定引发事件的文本框,但没有成功。
现在我感觉自己更加困惑了。非常感谢任何帮助。
4个回答

11
发送者方法应该是可以的。但是,您也可以进行类型转换:
TextBox txt = (TextBox) sender; // or "as" if you aren't sure.
                                // you can also just cast to Control for most
                                // common properties
// perhaps look at txt.Name, txt.Text, or txt.Tag

请注意,有一些情况下发送者可能不是你所认为的那个人,但这种情况很少见,主要与通过代码进行事件转发相关。例如:
public event EventHandler AcceptClick {
    add { acceptButton.Click += value;}
    remove { acceptButton.Click -= value;}
}

在这里,sender将是acceptButton,但你看不到它。通常情况下,这并不是一个问题。


7

有一个惯例,即传递给事件处理程序的第一个参数是发送事件的控件,因此您可以这样进行强制转换:

void myTextBox_EventHandler(object sender, EventArgs args)
{
    TextBox textBox = (TextBox)sender;
    ...
}

1

我认为Marc和GraemeF的答案很棒,但是我要添加一个答案(无论如何),作为一个稍微不同的方法的例子。这种方法反映了我的“懒散之路”:)编程哲学。请注意,此示例需要Linq。

我的第一个目标是拥有一个类型为TextBox的单个变量,可用于保存当前活动的TextBox(或者如果需要从表单外部访问它,则可以通过公共属性进行访问):如果我能够做到这一点,那么我就有了一种简单的方法来访问当前活动的TextBox的当前文本:只需使用.Text属性(无需转换)。

    //on the Form where the TextBoxes are : make into a Public Property
    // if you need to access this from outside the Form holding the TextBoxes
    // a Form-level variable
    private TextBox theActiveTB;

然后,在窗体上,我会使窗体加载事件为我构建一个文本框的集合,并确保它们订阅了相同的“KeyPress”和“Enter”事件。
   // on the Form where the TextBoxes are : a Form-level variable
    private List<TextBox> tbList;

    // build the list of TextBoxes and set the same 'Enter event for each of them
    // note the assumption that every TextBox on the Form is going to be handled
    // in exactly the same way : probably better to isolate them in a Panel in case
    // you have other TextBoxes for other purposes ; then you'd just use the same
    // code here to enumerate all the TextBoxes in the Panel
    private void Form1_Load(object sender, EventArgs e)
    {
         tbList =
         (
            from TextBox theTB in this.Controls.OfType<TextBox>()
            select theTB
         ).ToList();

         foreach (TextBox theTB in tbList)
         {
            theTB.KeyPress +=new KeyPressEventHandler(theTB_KeyPress);
            theTB.Enter +=new EventHandler(theTB_Enter);
         }
    }

    // so here's what the Enter event might look like :
    private void theTB_Enter(object sender, EventArgs e)
    {
        theActiveTB = (TextBox)sender;

        // reality check ...
        // Console.WriteLine("entering : " + theActiveTB.Name);
    }

    // so here's what the KeyPress event might look like :
    private void theTB_KeyPress(object sender, KeyPressEventArgs e)
    {
        // do what you need to do here

        // access the Text in the Textbox via 'theActiveTB

        // reality check
        // Console.WriteLine(theActiveTB.Name + " : " + e.KeyChar );
    }

为什么要使用Linq来创建List<TextBox>?毕竟,你可以通过循环遍历窗体(或面板或任何容器),检查每个控件的类型,然后如果它是一个TextBox,就在现场分配事件处理程序。我选择制作一个TextBoxes的通用列表的原因是:当我有一个具有特殊共享身份、目的或行为集合的集合时,通常情况下我会希望将其内容作为“集合”或“组”进行其他操作。


为了更加明确我之前所说的拥有相似元素/类/控件集合的优势,让我们假设我有一个包含你所有二十个文本框的List<TextBox>:我想要禁用它们所有:tbList.ForEach(tb => { tb.Enabled = false; }); …很好地解决了这个问题。最好的,Bill - BillW

1

您可以使用控件的tag属性来区分多个文本框。 为此,首先需要为每个文本框分配tag属性,在事件方法中,您可以访问tag属性。假设您想要分配多个参数,则可以创建一个具有参数作为属性的单独类,并将该类的对象分配给文本框的tag属性。

希望能对您有所帮助


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接