【问题标题】:How to find which control raised an event, while in so called event? Visual C#如何在所谓的事件中找到哪个控件引发了事件?视觉 C#
【发布时间】:2009-12-08 12:46:19
【问题描述】:

我正在编写一个 C# 程序,它接收一堆参数并对数据点进行一些转换,然后将它们绘制到屏幕上。

在我的一个表单上,我有一堆文本框,我都想执行相同的 KeyPress 事件。在我只做一个 switch 语句之前,它将只接收 KeyPress 事件的发送者并将其与所有 TextBoxes 进行比较。这种方法对我来说似乎不是很有效,因为现在我有 20 多个文本框。

我想做的是找到表单上的哪个 TextBox 发送了 KeyPress 事件并从该 TextBox 获取更多信息(即它的 Text 值等)。这将省去我必须与发件人进行巨大切换以查看它也相等的 TextBox 的麻烦。但我刚刚经历了最艰难的时期。

我查看了 System.Windows.Controls 和 System.Windows.Forms 类,看看是否能找到任何对我有帮助的东西。我正在寻找的是能让我看到哪个控件有焦点的东西。也许这就是我应该一直在寻找的东西?我还查看了我可以在 KeyPress 事件中对 sender 做什么,看看我是否可以弄清楚 TextBox 引发了事件,但仍然没有运气。

在这一点上,我觉得自己更加困惑了。任何帮助将不胜感激。

【问题讨论】:

    标签: c# winforms


    【解决方案1】:

    发件人方法应该没问题。但是,您可以投射:

    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,你看不到。不过,通常这不是问题。

    【讨论】:

      【解决方案2】:

      有一个约定,传递给事件处理程序的第一个参数是发送事件的控件,所以你可以这样转换:

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

      【讨论】:

        【解决方案3】:

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

        希望对你有帮助

        【讨论】:

          【解决方案4】:

          我认为 Marc 和 GraemeF 的答案很棒,但我将添加一个答案(无论如何)作为稍微替代方法的示例。这种方法反映了我的“松弛之路”:) 编程理念。请注意,此示例需要 Linq。

          我的第一个目标是拥有一个 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 ?毕竟,您可以只遍历表单(或面板,或任何容器)并检查每个控件的类型,然后,如果它是文本框,则立即分配事件处理程序。我选择为 TextBoxes 制作一个通用列表的原因是:当我有一个具有特殊共享标识、目的或一组行为的集合时,我通常会想用它的内容做其他事情作为“集合”或“组”。

          【讨论】:

          • 只是为了“具体化”我上面所做的声明,即在通用列表中拥有一组相似元素/类/控件的优点:假设我有一个 List 包含你所有的 20文本框:我想全部禁用它们:tbList.ForEach(tb => { tb.Enabled = false; }); ...很好地照顾它。最好的,比尔
          猜你喜欢
          • 2017-10-11
          • 1970-01-01
          • 2011-06-03
          • 2023-03-06
          • 2016-09-28
          • 2017-07-12
          • 1970-01-01
          • 2011-04-16
          • 2012-12-24
          相关资源
          最近更新 更多