From the June 2002 issue of MSDN Magazine.

MSDN Magazine

How to Use Objects

Download the code for this article: Basics0206.exe (88KB)

This month I'll tackle a couple of questions that deal with objects. If at first they don't seem to be about objects, remember just about everything in the .NET Framework is a class that becomes an object when instantiated.
Q** How do you stop a control like the LinkLabel that doesn't have a TabStop property from receiving focus when the user starts tabbing away?
A** Actually, the LinkLabel controls do have a TabStop property. I created the Windows® Form shown in Figure 1 to test this.

Figure 1 No Tabs
Figure 1 No Tabs

I added several LinkLabels and searched for the TabStop property in the Properties window. For some reason it doesn't show up in there. However, when I opened the Code window and started typing it in, IntelliSense® found it. You can add this code to your form to turn it off:

  LinkLabel1.TabStop = False
  

 

      Now, although this approach works, it's a little tedious to use on each and every control, so I created the following code to handle it automatically:

  Dim oControl As System.Windows.Forms.Control
  
Dim oLinklabel As System.Windows.Forms.LinkLabel

'Turn off tabstop for all linklabels
For Each oControl In Me.Controls
If oControl.GetType.ToString = _
"System.Windows.Forms.LinkLabel" Then
oLinklabel = CType(oControl, LinkLabel)
oLinklabel.TabStop = False
End If
Next

 

When placed in the Form_Load event, this code will disable the TabStop property on all the LinkLabels on the form each time the form loads.
      You can also use this code for other controls. Simply change the If statement inside the For Each loop to trap the control types you want to filter. You will also need to define a new reference to specific controls and set it in the If block. This makes it easy to perform many different operations on a group of controls.
Q** I have a master-detail form with a TabControl to display child objects. I want other master-detail forms to inherit from this one, and depending on the number of child objects used in the derived form, some of the TabPages I use must be hidden.
      The problem is that I'm unable to hide the TabPages when I change the Visible property to False in code. I'm allowed to do it only on the TabControl itself. (If you look at the properties in the derived form, you'll see that the Visible property for TabPages is not available.)
      Why can't I change the Visible property of individual TabPages? I have made sure that the Modifiers property of the TabPages is set to Protected.
A** This answer required a bit of research. First I created the MasterForm shown in Figure 2 for testing.

Figure 2 MasterForm
Figure 2 MasterForm

      As you can see, this form has a TabControl with three tabs. These tabs were created by right-clicking the control, selecting Add Tab, and entering a name. First, I tried setting the Visible property of the individual page by setting a reference to the tab and setting Visible to False. That didn't work. Puzzled, I started looking for examples in the MSDN® Help. The results are interesting and illustrate how .NET relies on objects everywhere.
      Take a look at the form. Part of the code for this page is shown in Figure 3. It includes the definition of the various controls that the designer created for the page. The following lines create one variable to reference the TabPage class for each tab in the control:

  Friend WithEvents TabPage1 As System.Windows.Forms.TabPage
  
Friend WithEvents TabPage2 As System.Windows.Forms.TabPage
Friend WithEvents TabPage3 As System.Windows.Forms.TabPage

 

Then, a few lines later, the TabControl variable is created:

  Protected WithEvents TabControl1 As _
  
System.Windows.Forms.TabControl

 

Later still, the AddRange method adds all of the TabPages to the TabControl.

  Me.TabControl1.Controls.AddRange(New _
  
System.Windows.Forms.Control() _
{Me.TabPage1, Me.TabPage2, Me.TabPage3})

 

The code that follows that sets properties such as Name and Size.
      You can see that each tab page is really an instance of the TabPage class. Looking into the properties of the TabPage class, I found that the Visible property is only accessible to the Framework classes, not to developers. That might explain why setting the visibility to False does not hide the tab. So, if you can't use it, why is it exposed?
      Now that I understood how the tabs were created, I thought I could attack the problem from an object perspective because each TabPage is part of the collection of TabPages in the TabControl.
      I looked for an Items collection. No luck. Then I tried a For Each loop but that involved too much overhead. After a bit more testing, I settled on this code:

  Dim TabPage1 As TabPage
  
TabPage1 = TabControl1.TabPages(1)
TabControl1.Controls.Remove(TabPage1)

 

The first line declares a variable of type TabPage. Then the next line sets that variable equal to the second tab page (zero-based collection). Now, TabPage1 points to the second tab. The last line removes the control. But how do you let the user put the control back on the tab?
      Knowing that everything is really an object, I thought I could create a collection to hold the TabPage, then take it out of the collection to put it back in the TabControl. So, I added the next line of code just before the Form_Load event to create the collection:

  Dim colRemovedTabs As New Collection()
  

 

This makes the collection public to the entire form. Next I changed the Hide 2 button's Click event code to this:

  Dim TabPage1 As TabPage
  
TabPage1 = TabControl1.TabPages(1)
colRemovedTabs.Add(TabPage1,
TabPage1.Name)
TabControl1.Controls.Remove(TabPage1)

 

      First a reference to the second tab is created, then the reference is added to the collection with the name of the tab used as the item's name in the collection. Then the Remove method of the TabControls collection is called to remove it.
      Next I added the code for the Add 2 button to put the tab back.

  'TabControl1.Controls.Add(colRemovedTabs(1))
  
TabControl1.Controls.Add(colRemovedTabs("TabPage2"))

 

It loads the tab after finding it in the collection and then passes the item returned from the collection (the TabPage) to the Add method of the Controls collection. I could have used the ordinal position (shown in the commented line) to retrieve the tab.
      Because I don't want a developer who inherits from MasterForm (see Figure 2) to be able to change the TabControl or the code behind the buttons, the controls on the MasterForm have their Modifiers property set to Friend.
      Next, I selected Add Inherited Form from the dropdown list, entered frmDerived for the name, and clicked Open. This fired up the Inheritance Picker dialog shown in Figure 4, where I selected the MasterForm and clicked OK to create the derived form.

Figure 4 Inheritance Picker
Figure 4 Inheritance Picker

      Believe it or not, the application is complete. MasterForm and frmDerived look practically the same except for Tab 2, whose visibility I can now control.

Conclusion

      One of the most important aspects of programming for the .NET Framework is the use of objects. Once you understand how to work with them, programming becomes more intuitive. In an ASP.NET class I taught recently, a developer asked how to randomly add a control to a Web Form. We walked through it together and in three minutes had a page that pulled data from a database and laid out the controls. All we did was create objects in a loop and add them to the collection on the page. Amazing!
Send questions and comments for Ken to basics@microsoft.com.**

Ken Spencer works for 32X Tech (https://www.32X.com) which provides training, software development and consulting services on Microsoft technologies.