If you have tried to override TabControl to add some custom behaviour, you certainly have noticed that it isn't easy to also override TabPage. Indeeed there's no way in a TabControl for specifying the type of TabPage we'd like to create. In design-mode a TabControl always creates a list of System.Windows.Forms.TabPage. This article explains how to override the TabPage control and ensure that the custom TabControl creates a list of custom TabPages.
Background
Warning, this article doesn't deals with any cool stuffs implemented in a custom TabControl. The aim is only to be able to override TabControl and TabPage, and to continue to fully support the Visual Studio designer. The solution contains a TabControlDesigner class, that reproduces exactly the behaviour of the original System.Windows.Forms.Design.TabControlDesigner. This designer has been used and tested by a development team, no developer has seen the difference between this TabControlDesigner and the original one.
Using the code
First, i have overriden TabControl and TabPage in MyTabControl and MyTabPage. In these custom classes you will be able to add your own implementations.
Then i created the custom TabControlDesigner class and declared it on MyTabControl. TabControlDesigner reproduces the behaviour of the original one. Particularly it allows to Add or Remove tab pages with the contextual menu, and to activate each TabPage for designing its content:
[Designer(typeof(DesignableTabControl.TabControlDesigner)]
public class MyTabControl : TabControl
In TabControlDesigner there is only one important line of code, it's the line that creates a new TabPage when you click the contextual menu entry "Add TabPage". You must take care to indicate the type of the good TabPage in CreateComponent:
TabPage page1 = (TabPage)host1.CreateComponent(typeof(MyTabPage)) as TabPage;
Now we are able to Add and Remove tab pages, but we cannot design within the TabPages. In fact MyTabPage still uses the Systm.Windows.Forms.Design.TabPageDesigner, and this class have some problems if there is no more the System.Windows.Forms.Design.TabControlDesigner. To solve this, we are going to use a ParentControlDesigner for MyTabPage:
[Designer(typeof(System.Windows.Forms.Design.ParentControlDesigner)]
public class MyTabPage : TabPage
That's all! We can now design the MyTabControl and its MyTabPages.
Points of Interest
When i see that it exists a method for creating our own control collections Control.CreateControlsInstance(); i think that it's really strange that .NET developers haven't implemented a method : TabControl.CreateTabPageInstance(). Don't you agree?
A warning for your further implementations: Perhaps you have already encountered an exception explaining that a custom control used in design-mode can be casted into its own type!! Visual Studio designer has some problems with cached dlls, and sometimes dlls used at design-time are loaded from two different locations. This is why it cannot cast a type into the same type loaded from a different location. Therefore i recommand, whenever it's possible, to manipulate the base TabPage and the base TabControl classes in your code. Indeed the designer has no problem with the base classes because there are always loaded from the System.Windows.Forms.dll located in the GAC. Another solution is to put your dll containing the custom controls in the GAC.