Thread: Finding controls from an event handler

  1. #1
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401

    Finding controls from an event handler

    Suppose I create a System.Windows.Form object within a function, and place a textbox and button on it. I then add a function to handle a click event for the button. How can I get access to the textbox from the event handler without declaring a class-wide variable? Ie:

    Code:
    namespace Foo
    {
    	class Bar
    	{
    		static void Main()
    		{
    			Form form=new Form();
    			TextBox text=new TextBox();
    			Button button=new Button();
    
    			button.Click+=new EventHandler(ButtonClick);
    			
    			form.Controls.Add(text);
    			form.Controls.Add(button);
    		}
    		private void ButtonClick(object sender, EventArgs e)
    		{
    			//How do I get access to "text" here?
    		}
    	}
    }
    Note that I do not want to make a new class for the form.

    How can I safely access the "text" object?
    [email protected]
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

  2. #2
    Banned nickname_changed's Avatar
    Join Date
    Feb 2003
    Location
    Australia
    Posts
    986
    First, I can't think of any good design that should lead to you doing this. If you need to do this in a real application,

    If you know the button and the text box are the only controls on the form, you can cycle through all the controls on the form, ie:

    Code:
    public void ButtonClick(object sender, EventArgs e)
    {
        // I can't remember if the property is called "Parent" or "Container":
        Form theForm = ((Control)sender).Parent;
    
        TextBox theTextBox;
        foreach (Control c in theForm.Controls)
        {
            if (c is TextBox)
            {
                theTextBox = (TextBox)c;
            }
        }
    
        if (theTextBox != null)
        {
            MessageBox.Show("Woohoo, the text is: " + theTextBox.Text);
        }
    }
    However, that's a disgusting solution.

    A better OOP way is to create a form that inherits from System.Windows.Forms, which exposes two things:

    Code:
    public class QuestionForm : Form
    {
    	// Expose an event people can subscribe to to know when the button is clicked:
    	public EventHandler ButtonClicked;
    	
    	// Expose the contents of the text box as a property of the form
    	public string Answer 
    	{
    		get
    		{
    			return textBox1.Text;
    		}
    	}
    	
    	// Rest of windows forms code:
    	private TextBox textBox1;
    	private Button button1;
    	
    	public QuestionForm()
    	{
    		textBox1 = new TextBox();
    		button1 = new Button();
    		
    		textBox1.Text = "Type here, sucker!";
    		button1.Text = "Click this!";
    		
    		button1.Click += new EventHandler(button1_Click);
    		
    		this.Controls.Add(textBox1);
    		this.Controls.Add(button1);
    	}
    	
    	private void button1_Click(object sender, EventArgs e)
    	{
    		// Fire our event handler to let other forms know the button was clicked
    		if (ButtonClicked != null)
    		{
    			ButtonClicked(this, EventArgs.Empty);
    		}
    	}
    }
    
    public class Program
    {
    	public static void Main(string[] args)
    	{
    		QuestionForm qf = new QuestionForm();
    		qf.ButtonClicked += new EventHandler(OnButtonClicked);
    		qf.Show();
    	}
    	
    	public void OnButtonClicked(object sender, EventArgs e)
    	{
    		// Someone clicked the button on the other form
    		QuestionForm qf = (QuestionForm)sender;
    		MessageBox.Show("Answer is: " + qf.Answer);
    	}
    }
    The idea is forms should be self containing - trying to access their controls from outside of the form goes against everything OOP stands for. If you need what's inside, have the form expose properties and events to "bubble up" other events (this is similar to what happens when you fart in the bath).

    Edit: Sorry, I just read you didn't want to make a new form.

    The first method is yucky because if you add another text box, there will be problems, and it's not very efficient. The second method is much more desirable, but you must have reasons for not doing it.

    Another method might be to use the Tag property on the text box to uniqely identify the text box. Just assign a string to the textbox's Tag property, and test in the loop that the tag is what is expected.

    Mind if I ask why you don't want to create a new form?
    Last edited by nickname_changed; 07-03-2005 at 03:37 AM.

  3. #3
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401
    Thanks, that first code is the way I eventually worked out, but yeah it's horrible. I didn't want to create a whole new class because it seemed so unnecessary for such a simple form. But I guess a new class is the only way to avoid messy hacks.

    Thanks for the help.
    [email protected]
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Lame null append cause buffer to crash
    By cmoo in forum C Programming
    Replies: 8
    Last Post: 12-29-2008, 03:27 AM
  2. event handler
    By hkl01 in forum C# Programming
    Replies: 1
    Last Post: 06-10-2006, 08:07 PM
  3. event handler for an array of buttons
    By GanglyLamb in forum C# Programming
    Replies: 4
    Last Post: 04-12-2005, 09:52 AM
  4. Tab Controls - API
    By -KEN- in forum Windows Programming
    Replies: 7
    Last Post: 06-02-2002, 09:44 AM