简体   繁体   中英

How to find which control raised an event, while in so called event? Visual C#

I am writing a C# program that takes in a bunch of parameters and does some transformations of data points and then draws them to screen.

On one of my forms I have a bunch of TextBoxes that I would all like to perform the same KeyPress event. Before I would just do a switch statement that would just take in the sender for the KeyPress event and compare it to all the TextBoxes. That method just doesn't seem very efficient to me as now I have 20+ TextBoxes.

What I would like to do is find which TextBox on the form sent the KeyPress event and get further information from that TextBox (IE its Text value, etc.). This would save me the trouble of having to do a huge switch with sender to see what TextBox it was equal too. But I have just been having the hardest time doing so.

I have looked through the System.Windows.Controls & System.Windows.Forms classes to see if I could find anything that would help me. What I was looking for was something that would let me see which control had focus. Maybe that was what I should have been searching for? I have also looked at what I can do with sender in the KeyPress event to see if I could figure out what TextBox raised the event and still no luck.

At this point I feel like I have confused myself more. Any help would be much appreciated.

The sender approach should be fine. You can, however, cast:

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

Note that there are scenarios where the sender isn't what you think, but this is the rarity, and mainly relates to event forwarding via code like:

public event EventHandler AcceptClick {
    add { acceptButton.Click += value;}
    remove { acceptButton.Click -= value;}
}

here, sender will be acceptButton , which you can't see. Normally this isn't a problem, though.

There is a convention that the first parameter passed to the event handler is the control that sent the event, so you can cast it like this:

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

You can use tag property of control to differentiate multiple textboxes. For this, First, you need to assign tag property for each textbox and in event method, you can access tag property. suppose you want to assign multiple parameters then create a separate class with parameters as properties and assign the object of the class to tag property of textbox.

Hope, It helps

I think Marc and GraemeF's answers are great, but I'm going to add an answer (anyway) as an example of a slightly alternative approach. This approach reflects my "path of slack" :) programming philosophy. Note this example requires Linq.

My first goal would be to have a single variable of type TextBox available to hold the current active TextBox (or if that needed to be accessed from outside the Form, I'd make it accessible via a public property) : if I can get that, then I have an easy way to access the current active TextBox's current Text : just use the .Text property (no conversion required).

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

Then, on the Form, I'd make the Form Load event build a collection of the TextBoxes for me : and make sure they subscribed to the same 'KeyPress and 'Enter events :

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

Why bother to make List<TextBox> using Linq ? You could, after all, just loop through the Form (or a Panel, or whatever container) and check each control's type, and then, if it's a TextBox, assign the Event Handlers right on the spot. The reason why I chose to make a generic list of the TextBoxes is because : when I have a collection with a special shared identity, or purpose, or set of behaviors, it's often the case that I will want to do other things with its content as a "set" or "group."

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM