Thread: C# Scoping Delinma

  1. #1
    Registered User
    Join Date
    Jan 2011
    Posts
    31

    C# Scoping Delinma

    Hello everyone,

    This is my first time on this forum but I hope i can someday become an accomplished community member. Anyways, I have a c# problem. Here's a quick description.

    Based on user input, i create different text boxes or buttons inside a function. Now i want to be able to detect when the data is altered within the program but the problem is that these text boxes or buttons are in the function's scope and not in global scope.

    I am using Visual Studio's C# 2008 which allows me to double clicked buttons already created on the form and generate the following:

    Code:
    private void button1_Click(object sender, EventArgs e)
    I don't know how else to handle button_clicks or textbox-altered events outside of double clicking the object on the C# form interface. Can you educate me on how I can handle these events in code and not rely on Visual Studio's C# interface?

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Visual Studio's C# interface?
    I suppose you mean instead of letting it auto generate the code for you and place it inside of InitializeComponent() in your <classname>.Designer.cs file?

    To add event handlers in C# you use the += operator. Check out the designer file and you will see all the editor is doing is hiding the setup from you but you can learn how to do it by looking at the InitializeComponent() method.

  3. #3
    Registered User
    Join Date
    Jan 2011
    Posts
    31
    Thanks for the tip! I've looked over the "hidden" code. After browsing on topics such as Events and Delegates (still not too sure what they are), I understood that eventhandler wanted a "function pointer".

    Thanks a lot for your help! My code is working fine now and I can make some progress.

    Here's a short segment of my code.
    Code:
                
    {
    Button addButton = new Button();
                addButton.Text = "Add Category";
                addButton.Location = new Point(25, 270);
                addButton.Click += new System.EventHandler(this.addButton_Clicked);
                this.Controls.Add(addButton);
            }
    
            private void addButton_Clicked(object sender, EventArgs e)
            {
                int testBreakPoint = 354;
            }

    Can you tell me if my understanding of Events and Delegates is incorrect?
    Events are triggers that will invoke functions when activated.
    Delegates are function pointers.

  4. #4
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Yes, that is correct.
    Just note that you can assign events in VS from the Property window in the event button (the one with the thunder symbol).

    Delegates are function pointers with the biggest maybe difference that they can have multiple functions and invoke all of them at once. For the difference of event and delegates you should google it! There are basically the same, except some differences that don't remember by heart.

    Note also that the "sender" argument in the function is always the control that calls the vent. So it is common to have one function and differentiate the behavior by doing something like:
    Code:
    private void someButton_Clicked(object sender, EventArgs e)
    {
                 Button b = sender as Button;
                //now you can use the right button clicked;
    }
    The event argument is some events associated, like if you press a key while on a control you can get which key you pressed etc

  5. #5
    Registered User
    Join Date
    Jan 2011
    Posts
    31
    Thanks for the reply and info! Interesting how sender is the object the control that calls it.

    Another scoping question then. Lets say ...

    Code:
    fooA()
    {
    TextBox descBox = new TextBox();
    this.Controls.Add(descBox);
    
    Button addButton = new Button();
    addButton.Click += new System.EventHandler(this.addButton_Clicked);
    this.Controls.Add(addButton);
    }
    
    private void addButton_Clicked(object sender, EventArgs e)
    {
          //some code
    }
    How can I access descBox.Text (or any other object) inside addButton_Clicked? Can i somehow use the EventArgs or create a new event with more arguments and simply pass that?
    Last edited by JohnLeeroy; 01-13-2011 at 05:13 PM.

  6. #6
    Registered User
    Join Date
    Aug 2003
    Posts
    1,218
    Just make descBox a member-variable of the class you are developing.

  7. #7
    Registered User
    Join Date
    Jan 2011
    Posts
    31
    I would like to do that but I am creating these objects(in the class Form1) during runtime so I couldn't do that. I could have a global variable holding the text for description box but that isn't as modular as I'd like.

  8. #8
    Registered User
    Join Date
    Aug 2003
    Posts
    1,218
    The Obvious:
    You are creating them runtime but you still have variables declared for them:
    TextBox descBox = new TextBox();
    Just move out TextBox descBox to be class scope instead. You can still instantiate it runtime.

    Otherwise i guess you could do some event-trickery where you trap the TextChanged event on descBox and use that update a local variable or something. But i really cant see why you cant just move out TextBox descBox to class-scope and instantiate it run-time.

  9. #9
    Registered User
    Join Date
    Jan 2011
    Posts
    31
    Well I want to be able to dynamically create objects in different scopes during run time and have access to them in certain functions.

    Lets say I am making a generic editor for the following:
    Employee Class - needs name, age, address, job type
    Item Class - needs unique ID and description

    Now i want to make an interface where there's a dropdown box of whether I'm making an employee or a new item. Based on user input, I would either make several different objects for the employee editor or two typeBoxes for the item editor.

    After an add button is clicked, I would update a listbox with what I've just added. I want to be able to have access to the information of what I want to add in my addButton_Clicked event.

    I know you are telling me to just create as many TextBoxes as I need for the largest class and assign their values during run-time but I find it crude to have to rely on uninitialized objects that may or may not be used i.e. in the case of the item.

    I hope I am understanding your suggestion correctly.
    Last edited by JohnLeeroy; 01-13-2011 at 06:37 PM.

  10. #10
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    What you will typically do is create a List<> of object references (pointers). So you can access the object through a reference, but the object is created in run-time.

    Note that a List<> dynamically resizes/shrinks so you won't have to know in advance how many objects you need.

    i.e.
    Code:
    List<TextBox> textboxes = new List<>();
    
    fooA()
    {
    TextBox descBox = new TextBox();
    this.Controls.Add(descBox);
    textBoxes.Add(descBox);
    
    Button addButton = new Button();
    addButton.Click += new System.EventHandler(this.addButton_Clicked);
    this.Controls.Add(addButton);
    }
    
    private void addButton_Clicked(object sender, EventArgs e)
    {
          //some code
         textBoxes[10].Text = ....;
    }
    Note that if you want to associate a Button with a text you can do so as well. Then if button 10 is clicked then you can read the Text from the associated TextBox 10.

    The way you manage the whole thing is up to you, there is always a way. The technique is to use a reference in the scope you want and instantiate objects wherever you want them to be created.

    In my example above, you could delete a TextBox from the textBoxes list if you wanted and the object will be deleted (collected) as well.

  11. #11
    Registered User
    Join Date
    Jan 2011
    Posts
    31
    Ahhh yes, this design will work out for me as I'll always create X number of textBoxes for classA and Y number of textBoxes for classB. I can just clear the list each time I want to make an instance of the other and rebuild it with the correct number of objects.

    Thanks for the design idea! You've been a great help!

  12. #12
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Be careful with events. Let's say you have a text changed event handler for a text box. Anytime you set the Text property of that text box the handler for that event will be called. This can lead to some strange event loops that yield very strange results. Some controls like the TreeView control allow you to account for this by using internal member variables that determine the cause of the change of a property. In custom handlers Microsoft recommends using a boolean to indicate the change was made from code instead of via an event. Your event handler checks if this boolean is set or not. If it is the event handler does nothing and returns. This is one of the biggest annoyances with events or more appropriately the use of C# events while using Windows Forms.
    Last edited by VirtualAce; 01-14-2011 at 05:51 PM.

  13. #13
    Registered User
    Join Date
    Jan 2011
    Posts
    31
    Quote Originally Posted by Bubba View Post
    Be careful with events. Let's say you have a text changed event handler for a text box. Anytime you set the Text property of that text box the handler for that event will be called. This can lead to some strange event loops that yield very strange results. Some controls like the TreeView control allow you to account for this by using internal member variables that determine the cause of the change of a property. In custom handlers Microsoft recommends using a boolean to indicate the change was made from code instead of via an event. Your event handler checks if this boolean is set or not. If it is the event handler does nothing and returns. This is one of the biggest annoyances with events or more appropriately the use of C# events while using Windows Forms.
    Debugging for an hour taught me that events are very sensitive. Not spending enough time to designing and making my code modular has caused initialization code to be recalled causing weird problems. Having a member boolean would help with the flow of code execution.

    C# Forms programming is quite the challenge and change compared to C++ which I am more familiar with.

  14. #14
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    C# Forms programming is quite the challenge
    The most challenging part of it, IMO, is figuring out what was going through the heads of the folks at Redmond when they designed it. There are books about Forms programming but with the advent of WPF I have not found any new books written just for Windows Forms.

  15. #15
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Quote Originally Posted by Bubba View Post
    Be careful with events. Let's say you have a text changed event handler for a text box. Anytime you set the Text property of that text box the handler for that event will be called. This can lead to some strange event loops that yield very strange results. Some controls like the TreeView control allow you to account for this by using internal member variables that determine the cause of the change of a property. In custom handlers Microsoft recommends using a boolean to indicate the change was made from code instead of via an event. Your event handler checks if this boolean is set or not. If it is the event handler does nothing and returns. This is one of the biggest annoyances with events or more appropriately the use of C# events while using Windows Forms.
    Or alternatively, use the "sender" argument of the event.

    Code:
    private void addButton_Clicked(object sender, EventArgs e)
    {
       // probably sent from code
       if(sender == null)
       {
          // do code-wise stuff
       }
       else
       {
          Button button = sender as Button;
    
          if(button != null)
          {
             button.Text = "You just clicked me";
          }
       }
    }
    Of course, you now have to be careful of times where the sender is null when it's called from non-code. But I agree, how is this better than C function pointers, oh that's right -- they're "type safe" and chain :-/.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Errors: ISO scoping, obsolete binding??
    By -JM in forum C++ Programming
    Replies: 3
    Last Post: 10-28-2005, 08:56 PM
  2. scoping visibility
    By dirgni in forum C++ Programming
    Replies: 2
    Last Post: 12-02-2002, 04:16 PM