Overcome Limitations With TabControl
Learn how to customize TabControl components. The author shows you how to fix shortcut keys on TabControl and hide and show TabControl pages.
Technology Toolbox: VB.NET
Fix Shortcut Keys on TabControl
My VB.NET Windows Form contains a TabControl to group my many data fields. I use shortcut keys so the user can use the Alt key to jump to fields quickly. However, the shortcut key stops working completely if I use the same shortcut key on two different pages of the TabControl. How do I fix this?
Giving each field a unique shortcut key is a good idea, but you start running into conflicts once you reach about 20 controls on your form. You could modify each label and control manually, weeding out ampersand characters, but it's easier to do this generically. Build a custom TabControl that adds a shortcut management feature (see Listing 1). Use this custom ShortcutTabControl on your form instead of TabControl.
The code creates a new class that inherits from Windows.Forms.TabControl. You need two local variables to track the shortcuts:
Private shortcutLookup As New _
Private lastTab As Windows.Forms.TabPage
Now all you need are two routines: one method to initialize everything, and one method that does the processing each time the tab page changes. The first method, InitShortcuts, gets everything ready for when you need to make a tab switch. It builds a list of control names with their original Text property values. For controls with shortcut keys, this includes any ampersand characters. While InitShortcuts makes this list, it strips all controls not on the currently selected tab of their ampersand characters.
You need to call InitShortcuts right away when the form appears, so call it from the Load event of the form that contains the custom TabControl. InitShortcuts modifies all nonblank text fields, so make sure you call the routine before you populate any of your text fields with real data, just in case that data includes ampersand characters. Also, the sample code I've provided assumes that a shortcut indicator is the only use for an ampersand. If you have a label such as "&Cats && Dogs," all three ampersands will disappear, but only while its tab is hidden. If desired, you can enhance the sample code to take these and other data issues into account.
The second custom routine, OnSelectedIndexChanged, makes all of the Text property changes needed to mask conflicting shortcuts. The routine is actually an override of the TabControl's protected OnSelectedIndexChanged method. First, it removes any shortcuts from all controls on the tab page you just left. Then it restores all shortcuts on the newly selected tab. Both of these steps are only done for controls that show up in the shortcutLookup collection. This prevents you from modifying real user data in text fields. You must call the same method on the base class before leaving this method; otherwise, the whole TabControl is unresponsive to the user, appearing to be dead:
The form calls the OnSelectedIndexChanged method once before the user even sees it. Visual Studio also calls the form in design mode so you can manipulate the individual tab pages. An If statement at the start of the routine checks for these two conditions.
Hide and Show TabControl Pages
I need to hide and show pages of my TabControl based on user settings in other fields on my form. Which TabControl features can I use to do this?
The TabControl's TabPages collection has useful Add and Remove methods that let you add and remove tab pages dynamically (see Figure 1). If all you want to do is hide tabs and never redisplay them, you use the TabPages.Remove method by passing it a reference to the TabPage object you want to remove. (The related TabPages.RemoveAt does the same thing, but it uses a zero-based index into the collection of tab pages.) Adding a tab back in, though, is a little harder because the TabPages.Add method always appends the page to the end of the collection, not back into its original position. You can solve this problem easily by using a custom TabControl with a new InsertTabAt method (see Listing 2). Add this custom ShowHideTabControl on your form instead of the basic TabControl.
Use the InsertTabAt method by passing a reference to a previously removed TabPage object to it, plus a zero-based position where you want the page to appear. The routine adds the new page to the end of the TabPages collection after it performs some error checking. Then, one by one, it removes each of the pages that should appear after the new page, and adds them to the end of the collection again.
You don't need to create temporary variables to hold the pages you remove from your ShowHideTabControl. Form-level variables exist already for each page. For instance, if you create a TabControl with three pages, the default names of the pages (and the form-level variables) are TabPage1, TabPage2, and TabPage3. Simply refer to these names when using the InsertTabAt method:
It is possible to add the same TabPage object into a TabControl multiple times, so make sure you keep track of which pages you add and remove so as not to confuse the user. Also, the Add and Remove/RemoveAt methods sometimes alter which remaining or new tab is the currently selected tab. You should reselect the expected active tab page as needed after adding or removing other pages.
About the Author
Tim Patrick has spent more than thirty years as a software architect and developer. His two most recent books on .NET development -- Start-to-Finish Visual C# 2015, and Start-to-Finish Visual Basic 2015 -- are available from http://owanipress.com. He blogs regularly at http://wellreadman.com.