Working with Controls Dynamically in Code
Each control in the Toolbox is a member of the Control class in the System.Windows.Forms namespace. Because each control in the Toolbox is a class, similar to a Window Forms class, you can dynamically create controls in code at runtime. Earlier you looked at the InitializeComponent method, which created the controls on the form. You can do the same type of dynamic code creation when writing applications. Doing so gives you flexibility in the user interface and enables you to create complete forms based on user settings that might be stored in a database or configuration file.
To find out how to create controls dynamically at runtime, add the code in Listing 3.4 to the Form_Load event of firstForm.
Listing 3.4 Creating Controls Dynamically at Runtime
VB.NET
Private Sub firstForm_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Declare new instances of the RadioButton control class Dim Rd1 As RadioButton = New RadioButton() Dim Rd2 As RadioButton = New RadioButton() Dim Rd3 As RadioButton = New RadioButton() ' Position the controls Rd1.Location = New System.Drawing.Point(15, 90) Rd2.Location = New System.Drawing.Point(15, 120) Rd3.Location = New System.Drawing.Point(15, 150) ' Assign a text value for these controls Rd1.Text = "Red" Rd2.Text = "White" Rd3.Text = "Blue" ' Add to the forms controls collection Me.Controls.AddRange(New Control() {Rd1, Rd2, Rd3}) ' Add event handlers for the controls AddHandler Rd1.Click, AddressOf GenericClick AddHandler Rd2.Click, AddressOf GenericClick AddHandler Rd3.Click, AddressOf GenericClick End Sub Public Sub GenericClick(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Select Case sender.text Case "Red" Me.BackColor = Color.Red Case "White" Me.BackColor = Color.White Case "Blue" Me.BackColor = Color.Blue End Select End Sub
C#
private void firstForm_Load(object sender, System.EventArgs e) { // Declare new instances of the RadioButton control class RadioButton rd1 = new RadioButton(); RadioButton rd2 = new RadioButton(); RadioButton rd3 = new RadioButton(); // Position the controls rd1.Location = new System.Drawing.Point(15, 90); rd2.Location = new System.Drawing.Point(15, 120); rd2.Location = new System.Drawing.Point(15, 150); // Assign a text value for these controls rd1.Text = "Red"; rd2.Text = "White"; rd3.Text = "Blue"; // Add to the forms controls collection this.Controls.AddRange(new Control[] {rd1, rd2, rd3}); // Add the generic event handler rd1.Click += new System.EventHandler(genericClick); rd2.Click += new System.EventHandler(genericClick); rd3.Click += new System.EventHandler(genericClick); } private void genericClick(object sender, System.EventArgs e) { RadioButton rdb; rdb = (RadioButton)sender; this.BackColor = Color.FromName(rdb.Text); }
After the code is in, press F5 to run the application. You'll see that the three RadioButton controls appear on your form. Just like any other object, declaring a new instance of a control gives you the properties, methods, and events for that control. In Visual Basic 6, you could dynamically create controls with the New keyword, and then set the Right, Left, and Top properties to position them, but you needed to set the Visible property to True for them to show up on the form. In .NET, you set the X and Y screen coordinates of the newly created controls, and then add the controls to the form's Controls collection with the AddRange method.
The AddRange method takes an array of controls and adds them to the Controls collection. After the controls are added to the Controls collection, you add an event handler delegate to tell the control what event should fire and what method should handle the event. Inside the genericClick event, you accept the System.Object and System.EventArgs parameters. By accepting the System.Object parameter, the object that's associated with the event handler is passed to the event handler. So, you can convert the System.Object to the correct type (in this case, the type is RadioButton), and have available its properties, methods, and events. This is an immensely efficient way of handling multiple events with a single event handler. In the genericClick event, the Text property of the RadioButton is converted to a Color type, which has a FromName method to convert a common color name to the actual System.Drawing.Color type.
In the Visual Basic .NET code, I used the Select Case statement as an example of another great feature in .NET. When you typed in Select Case sender.Text and pressed the Enter key, the End Select was automatically added. This same behavior occurs in If...Then statements and With...End With statements, to name a few. On Day 8, "Core Language Concepts in Visual Basic .NET and C#," you learn about the language features of both Visual Basic .NET and C#, and you'll see the advantages of the Code Editor in more detail when you're using all the language features.