Tabbed Pages

A loose-leaf notebook with tabbed separator pages is an efficient way to organize and present a large amount of information in a compact space. The labeled tab on each separator page clearly separates and identifies the contents of that section. Although you can be in only one section at a time, you can easily see the labels of all available sections and instantly move between them.

This tabbed notebook metaphor, a common user interface design pattern in the Windows world, is implemented in .NET with the TabControl, which contains a collection of TabPage objects. All TabPage objects are layered one on top of another, with only one tab page visible at a time. Select which page to view by clicking on the tab. Each tab page can contain any number of controls.

Referring back to the class hierarchy displayed in Figure 13-1, you can see that the TabControl class is directly derived from the Control class, while the TabPage class is derived from Control via ScrollableControl and Panel. The TabControl control cannot contain other controls, except for TabPage objects. The TabPage objects, on the other hand, can contain other controls and have scrollbars. Unlike the Panel control from which it is derived, the TabPage displays its Text property as the text string on the tab.

The TabControl control has many properties in addition to those inherited from Control. Many are listed in Table 13-1.

Table 13-1. TabControl properties


Value type




Read/write. The edge of the control where the tabs are located. Valid values are members of the TabAlignment enumeration, listed in Table 13-2. The default is TabAlignment.Top.

If set to Left or Right, the Multiline property is automatically set to true.



Read/write. The visual appearance of the tabs. Valid values are members of the TabAppearance enumeration, listed in Table 13-3. The default is TabAppearance.Normal.



Read-only. Returns a Rectangle representing the display area of the tab pages.



Read/write. Allows users to customize how the control is drawn. If it is TabDrawMode.Normal, the default, the operating systems draws the tabs. If it is TabDrawMode.OwnerDrawFixed, the tabs are drawn by the parent window.



Read/write. If false (the default), tabs do not change the appearance when the mouse passes over. If true, the color of the tab text will change.



Read/write. Specifies the ImageList containing images to be displayed on the tabs. The TabPage.ImageIndex property specifies which image to actually use. (The ImageList is described in Chapter 7.)



Read/write. The size of the tabs. The default size automatically fits images and Text properties.

The SizeMode property must be set to Fixed to change the ItemSize.Width property.



Read/write. If false (the default), only one line of tabs will be displayed. If there are more tabs than will fit, arrows will be displayed to allow navigation to undisplayed tabs.

If false, the Alignment property is automatically set to TabAlignment.Top.



Read/write. The amount of space around the text on the tab. Default is (6,3).



Read-only. Returns the number of rows of tabs currently displayed.



Read/write. Zero-based index of the currently selected tab page.



Read/write. If false (the default), ToolTips are not shown for tabs that have them. To create a ToolTip for a tab, set the TabPage.ToolTipText property.



Read/write. Specifies how the tabs are sized. Valid values are members of the TabSizeMode enumeration, listed in Table 13-4. The default is TabSizeMode.Normal.



Read-only. Number of tabs in the TabControl.



Read-only. The collection of tab pages contained in the control. The TabPageCollection class has properties, listed in Table 13-5, and methods, listed in Table 13-6.



Read/write. Overrides Control.Text. Similar to the Panel controldoes not display anywhere.

Table 13-2. TabAlignment enumeration




Tabs located along the bottom of the control.


Tabs located along the left edge of the control.


Tabs located along the right edge of the control.


Tabs located along the top of the control.

Three of the four possible values of TabAlignment are shown in Figure 13-2. The missing Right value is symmetrical to the Left.

Figure 13-3. TabAlignment


Table 13-3. TabAppearance enumeration




Tabs look like 3-D buttons.


Tabs look like flat buttons.


Tabs look like standard tabs.

Table 13-4. TabSizeMode enumeration




Tabs are sized so that each row of tabs completely fills the width of the TabControl. Only applicable if Multiline is set to true and there is more than one row of tabs.


All the tabs are the same width.


Each tab is sized for the contents of the tab and not adjusted to fill the width of the TabControl.

The Alignment and Appearance properties of the TabControl depend on each other for correct operation. If the Alignment property is set to TabAlignment.Top, then everything works fine regardless of the Appearance property. However, if the Alignment property is set to any value other than Top, the tab pages themselves will appear to be missing unless the Appearance property is set to the default of TabAppearance.Normal. If the Appearance is set to TabAppearance.Buttons or TabAppearance.FlatButtons, the tabs will display as buttons only and events will still fire, but the tab pages themselves will again appear to be missing. Furthermore, the tabs can appear as FlatButtons only if the Alignment is set for Top; if the Alignment is not set for Top, then FlatButtons will appear as Buttons.

The Padding property adds space around the text displayed in the tab. The left image in Figure 13-3 shows tabs using the default value for Padding (6,3) while the right image shows the Padding property set to (20,10). Notice that the Multiline property is set to true for both images: only the right image needed more than one row of tabs. If Multiline had not been set to true, the tabs would display in a single row with a clickable arrow for navigating to the other tabs.

If the vertical size of the Padding is set larger than default and Multiline is false, the tabs may display with part of the text truncated if there are more tabs than will fit in a one row.


Figure 13-4. TabControl Padding property


All the tab pages contained by the TabControl are members of the TabPageCollection class. The commonly used properties and methods of the TabPageCollection class are listed in Table 13-5 and Table 13-6, respectively.

Table 13-5. TabPageCollection properties


Value type




Read-only. Returns the number of tab pages in the collection (the number of tab pages in the TabControl).



Read-only. Always returns false.



Read/write. The tab page at the zero-based index specified by this property.

Table 13-6. TabPageCollection methods




Adds a TabPage object to the collection.


Adds multiple TabPage object to the collection.


Removes all TabPage objects from the collection.


Returns true if the specified TabPage is in the collection.


Returns an enumerator containing all the TabPage objects. Changing the enumerator changes the collection of TabPages.


Returns the zero-based index of the specified TabPage object or -1 if the object not found.


Removes the specified TabPage object.


Removes the TabPage object at the specified zero-based index.

Each tab page in a TabControl can also have properties of its own. The commonly used properties are listed in Table 13-7.

Table 13-7. TabPage properties


Value type




Read/write. The index of the image to display on the tab. The zero-based index is in the ImageList specified in the TabControl.ImageList property.



Read/write. Overridden. The zero-based index of the tab page within the TabPage collection.



Read/write. The text displayed on the tab.



Read/write. The text displayed as a ToolTip when the user's mouse passes over the tab, if the TabControl.ShowToolTips property is set to true.

The TabPage TabIndex property is not listed as a member of the TabPage class in the SDK documentation that ships with the .NET Framework (although if you search, it will show up). It also does not show up in the IntelliSense list of all available members for a TabPage object in Visual Studio .NET. However, it will compile and return the value listed in Table 13-7. This functionality is entirely different from the TabIndex property of the Control class.

Its existence can be confirmed by the WinCV class viewer utility, which ships as part of the SDK. To run this utility, open a .NET command prompt (Start Programs Microsoft Visual Studio .NET 2003 Visual Studio .NET Tools Visual Studio .NET 2003 Command Prompt) and enter the command WINCV.

Other than events inherited from Control, the one commonly used event raised by the TabControl control is SelectedIndexChanged. It is raised whenever a different tab page is selected. Its usage will be demonstrated shortly.

There is actually a second event raised by the TabControl control: DrawItem. It occurs when the tabs are drawn if the DrawMode property was set to TabDrawMode.OwnerDrawFixed. This allows the parent window to draw the tab, giving you control over the appearance of the tabs.

The TabPage class has one method not inherited from the Control or other base class: GetTabPageFromComponent. This static (Shared in VB.NET) method takes a single object as an argument. This method will return the TabPage object containing the component if the component is found; otherwise it will return null (Nothing in VB.NET). For example, if you wanted to find and make current the tab page in a tab control that contains a RichTextBox control called rtxt, you could use a line such as the following:


tc.SelectedIndex =


tc.SelectedIndex = _

The programs listed in Example 13-3 (in C#) and Example 13-4 (in VB.NET) demonstrate many of the features of the TabControl and TabPage classes. In these programs, a tab control is created on a form. This tab control contains four tab pages, three of which actually contain other controls and the fourth of which has a spiffy wrench icon as part of its tab. The look of the tabs is controlled using the Alignment, Appearance (which is set to its default value), Multiline, Padding, and SizeMode properties. When either program is compiled and run, the first three pages will look like Figure 13-4. The fourth tab page, labeled "A Really Long Tab," contains no controls. It exists mainly to highlight the effects of these properties.

Figure 13-5. TabControl and TabPages


An analysis of Example 13-3 and Example 13-4 follows the code listings.

Example 13-3. TabControl and TabPages in C# (TabControls.cs)


using System;
using System.Drawing;
using System.Windows.Forms;
namespace ProgrammingWinApps
 public class TabControls : Form
 public TabControls( )
 Text = "TabControl & TabPages";
 Size = new Size(325,375);
 TabControl tc = new TabControl( );
 tc.Parent = this;
 tc.Size = new Size(275,300);
 tc.Location = new Point(25,25);
 tc.Anchor = AnchorStyles.Top | AnchorStyles.Bottom |
 AnchorStyles.Left | AnchorStyles.Right;
 tc.Alignment = TabAlignment.Top;
 tc.Appearance = TabAppearance.Normal;
 tc.HotTrack = true;
 tc.Multiline = true;
 tc.Padding = new Point(20,3);
 tc.SizeMode = TabSizeMode.FillToRight;
 tc.SelectedIndexChanged += new EventHandler(tc_Changed);
 tc.Text = "Some text";
 // Get an image for one of the tabs
 Image img = Image.FromFile(
 "C:\Program Files\Microsoft Visual Studio .NET 2003" + 
 ImageList imgList = new ImageList( );
 tc.ImageList = imgList;
 // Address book tab
 TabPage tpAddress = new TabPage( );
 tpAddress.Parent = tc;
 tpAddress.Text = "Address Book";
 // Datebook tab
 TabPage tpDates = new TabPage( );
 tpDates.Parent = tc;
 tpDates.Text = "Date Book";
 // ToDo tab
 TabPage tpToDo = new TabPage( );
 tpToDo.Parent = tc;
 tpToDo.Text = "ToDo List";
 // Miscellaneous tab
 TabPage tpMisc = new TabPage( );
 tpMisc.Parent = tc;
 tpMisc.Text = "A Really Long Tab";
 tpMisc.ImageIndex = 0;
 // Address stuff
 Label lbl = new Label( );
 lbl.Parent = tpAddress;
 lbl.Text = "Put the Address book controls on this page.";
 lbl.AutoSize = true;
 lbl.Location = new Point(10,25);
 // Datebook stuff
 Panel pnl = new Panel( );
 pnl.Parent = tpDates;
 pnl.BorderStyle = BorderStyle.Fixed3D;
 pnl.Location = new Point(10,10);
 pnl.Anchor = AnchorStyles.Top | AnchorStyles.Bottom |
 AnchorStyles.Left | AnchorStyles.Right;
 pnl.Size = new Size(tpDates.Width - 20, tpDates.Height - 20);
 MonthCalendar cal = new MonthCalendar( );
 cal.Parent = pnl;
 cal.Location = new Point(25,25);
 // ToDo stuff
 RichTextBox rtxt = new RichTextBox( );
 rtxt.Parent = tpToDo;
 rtxt.Dock = DockStyle.Fill;
 rtxt.BorderStyle = BorderStyle.FixedSingle;
 } // close for constructor
 static void Main( ) 
 Application.Run(new TabControls( ));
 private void tc_Changed(object sender, EventArgs e)
 TabControl tc = (TabControl)sender;
 MessageBox.Show("Button " + tc.SelectedIndex.ToString( ));
 } // close for form class
} // close form namespace

Example 13-4. TabControl and TabPages in VB.NET (TabControls.vb)


Option Strict On
imports System
imports System.Drawing
imports System.Windows.Forms
namespace ProgrammingWinApps
 public class TabControls : inherits Form
 public sub New( )
 Text = "TabControl & TabPages"
 Size = new Size(325,375)
 dim tc as new TabControl( )
 tc.Parent = me
 tc.Size = new Size(275,300)
 tc.Location = new Point(25,25)
 tc.Anchor = AnchorStyles.Top or AnchorStyles.Bottom or _
 AnchorStyles.Left or AnchorStyles.Right
 tc.Alignment = TabAlignment.Top
 tc.Appearance = TabAppearance.Normal
 tc.HotTrack = true
 tc.Multiline = true
 tc.Padding = new Point(20,3)
 tc.SizeMode = TabSizeMode.FillToRight
 AddHandler tc.SelectedIndexChanged, AddressOf tc_Changed
 tc.Text = "Some text"
 ' Get an image for one of the tabs
 dim img as Image = Image.FromFile( _
 "C:\Program Files\Microsoft Visual Studio .NET 2003\" + _
 dim imgList as new ImageList( )
 tc.ImageList = imgList
 ' Address book tab
 dim tpAddress as new TabPage( )
 tpAddress.Parent = tc
 tpAddress.Text = "Address Book"
 ' Datebook tab
 dim tpDates as new TabPage( )
 tpDates.Parent = tc
 tpDates.Text = "Date Book"
 ' ToDo tab
 dim tpToDo as new TabPage( )
 tpToDo.Parent = tc
 tpToDo.Text = "ToDo List"
 ' Miscellaneous tab
 dim tpMisc as new TabPage( )
 tpMisc.Parent = tc
 tpMisc.Text = "A Really Long Tab"
 tpMisc.ImageIndex = 0
 ' Address stuff
 dim lbl as new Label( )
 lbl.Parent = tpAddress
 lbl.Text = "Put the Address book controls on this page."
 lbl.AutoSize = true
 lbl.Location = new Point(10,25)
 ' Datebook stuff
 dim pnl as new Panel( )
 pnl.Parent = tpDates
 pnl.BorderStyle = BorderStyle.Fixed3D
 pnl.Location = new Point(10,10)
 pnl.Anchor = AnchorStyles.Top or AnchorStyles.Bottom or _
 AnchorStyles.Left or AnchorStyles.Right
 pnl.Size = new Size(tpDates.Width - 20, tpDates.Height - 20)
 dim cal as new MonthCalendar( )
 cal.Parent = pnl
 cal.Location = new Point(25,25)
 ' ToDo stuff
 dim rtxt as new RichTextBox( )
 rtxt.Parent = tpToDo
 rtxt.Dock = DockStyle.Fill
 rtxt.BorderStyle = BorderStyle.FixedSingle
 end sub ' close for constructor
 public shared sub Main( ) 
 Application.Run(new TabControls( ))
 end sub
 private sub tc_Changed(ByVal sender as object, _
 ByVal e as EventArgs)
 dim tc as TabControl = CType(sender,TabControl)
 MessageBox.Show("Button " + tc.SelectedIndex.ToString( ))
 end sub
 end class
end namespace

These sample programs don't do much, so almost all of the action occurs inside the constructor. A TabControl object is declared, instantiated, and given a size and location. Its Anchor property is set so the tab control will automatically resize itself if the user resizes the form, retaining the same margins on all four sides with respect to the form.

Several properties of the tab control are set, including Alignment, Appearance (which is set to its default value), Multiline, Padding, and SizeMode. Setting the HotTrack property to true causes the tab text to change color when the mouse moves over the tab.

The SizeMode property, set in these examples to TabSizeMode.FillToRight, profoundly affects the appearance of the tabs if any of the tabs are of significantly different length and/or if there are more tabs than will fit on one row. The valid values of this property are listed in Table 13-4. The effects of each possible value of the property are seen in Figure 13-5.

Figure 13-6. TabControl SizeMode property: FillToRight, Fixed, and Normal


An event handler method is added to the delegate for the TabControl SelectedIndexChanged event:


tc.SelectedIndexChanged += new EventHandler(tc_Changed);


AddHandler tc.SelectedIndexChanged, AddressOf tc_Changed

Every time the user selects a new tab, this event will be fired, invoking the event handler method tc_Changed. That event handler puts up a message box in this example, but it could do other useful things, such as logging page hits or updating the database.

The event argument for this event is of type EventArgs, so there is no additional information passed about the event. However, the object named sender can be cast back to a TabControl object (which is safe in this case and will not raise an exception), and then all of the TabControl properties are available to the method, including the SelectedIndex property, as shown in the event handler (reproduced here):


private void tc_Changed(object sender, EventArgs e)
 TabControl tc = (TabControl)sender;
 MessageBox.Show("Button " + tc.SelectedIndex.ToString( ));


private sub tc_Changed(ByVal sender as object, _
 ByVal e as EventArgs)
 dim tc as TabControl = CType(sender,TabControl)
 MessageBox.Show("Button " + tc.SelectedIndex.ToString( ))
end sub

The next several lines of code create an ImageList and populate it with a single image, wrench.ico, which is a standard icon file included with Visual Studio .NET. The ImageList is assigned to the tab control's ImageList property. You need to create the ImageList even though only a single image is used because the TabPage class has an ImageIndex property (listed in Table 13-7) but no Image property, as does the Button class, for example. This image list will be used shortly to put the wrench icon on the fourth tab page.

The four tab pages are instantiated and specified. Each follows the same pattern. The tab page object is instantiated and assigned to a variable. The Parent property of the object is set to the TabControl object, and its Text property is set. The fourth tab page also has its ImageIndex property set to 0 so the wrench icon will display:


TabPage tpAddress = new TabPage( );
tpAddress.Parent = tc;
tpAddress.Text = "Address Book";
tpMisc.ImageIndex = 0;


dim tpAddress as new TabPage( )
tpAddress.Parent = tc
tpAddress.Text = "Address Book"
tpMisc.ImageIndex = 0

If this project were implemented in Visual Studio .NET, the Parent property would not be set this way. Instead, an array of Control objects would be created by Visual Studio .NET, and the AddRange method used to add the array of TabPage objects to the TabControl object's Controls collection. It would look something like:

 System.Windows.Forms.Control[ ] {
 this. tpAddress,
 this. tpDates,
 this. tpToDo,

figs/vbicon.gif _
 New System.Windows.Forms.Control( ) _
 {Me.tpAddress, Me.tpDates, Me.tpToDo, _
 _Me.tpMisc })

which can be seen by expanding the Windows Form Designer generated code.

Each of the first three tabs then has one or more controls added to them. Adding controls to a tab page is the same as adding controls to a form, except that the Parent property of each control is set to the appropriated TabPage object rather than the form.

Referring to the previous note, the Parent property of each control is implicitly set in Visual Studio .NET by using the AddRange method.


13.2.1 Tabbed Pages Using Visual Studio .NET

In Visual Studio .NET, most controls are represented by an icon in the Toolbox, and can be either dragged onto the form or double-clicked to be placed on the form. The TabControl control follows that model: there is an icon for the TabControl in the Toolbox (figs/icon_tabcontrolicon.gif) that can be either double-clicked or dragged onto a form. However, the TabPage control in the Toolbox has no icon.

There are two different ways to add TabPage objects to a TabControl control, aside from manually coding them as was done earlier in this chapter. The first way is to select and right-click the TabControl control in Design view, and then click on the Add Tab menu item from the pop-up menu. This will add a tab page directly to the tab control, with a default name of tabPage1 (tabPage2, and so on). Once the tab page is added, you can set its properties by selecting it in Design view and editing the properties in the Properties window.

The second way to add tab pages is to select the tab control in Design view, locate the TabPages property in the Properties window, and click on the Build button (...). This will bring up the TabPage Collection Editor dialog box, shown in Figure 13-6. This dialog box has buttons for adding and removing tab pages, as well as a Properties window for setting the properties of the currently selected tab page. It also has buttons for easily changing the order of the tab pages.

No matter which technique you use, you can use either the Properties windowthe one in the main Visual Studio .NET window or the one in the TabPage Collection Editorto edit the properties of the currently selected tab page.

Figure 13-7. TabPage Collection Editor in Visual Studio .NET


Windows Forms and the .NET Framework

Getting Started

Visual Studio .NET


Windows Forms

Dialog Boxes

Controls: The Base Class

Mouse Interaction

Text and Fonts

Drawing and GDI+

Labels and Buttons

Text Controls

Other Basic Controls

TreeView and ListView

List Controls

Date and Time Controls

Custom Controls

Menus and Bars


Updating ADO.NET

Exceptions and Debugging

Configuration and Deployment

Programming. NET Windows Applications
Programming .Net Windows Applications
ISBN: 0596003218
EAN: 2147483647
Year: 2003
Pages: 148 © 2008-2020.
If you may any questions please contact us: