Design Custom TabPage in C# WinForms?

14,366

Solution 1

If you make a user control that contains your tabcontrol you can see the designer and design it as you like, and you can add some additional code, and still can drag & drop it from toolbox to use it.

Note: you can't see you user control (neither your manually coded class) untill you Rebuild your project

Solution 2

You can create your own TabControl designer, and implement the functionality you need at design time. Here is the code of the simplest version of such designer:

using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.ComponentModel.Design;
using CustomTabControlExample.TabControl;

namespace CustomTabControlExample.Design {
    public class CustomTabControlDesigner :ParentControlDesigner {
        DesignerVerbCollection fVerbs;
        public override DesignerVerbCollection Verbs {
            get {
                if (fVerbs == null)
                    fVerbs = new DesignerVerbCollection(new DesignerVerb[] {
                        new DesignerVerb("Add Tab", OnAdd)
                        });
                return fVerbs;
            }
        }

        void OnAdd(object sender, EventArgs e) {
            TabPage newPage = (TabPage)((IDesignerHost)GetService(typeof(IDesignerHost))).CreateComponent(
                typeof(CustomTabPage));
            newPage.Text = newPage.Name;
            ((System.Windows.Forms.TabControl)Component).TabPages.Add(newPage);
        }

        public override void InitializeNewComponent(IDictionary defaultValues) {
            base.InitializeNewComponent(defaultValues);
            for (int i = 0; i < 2; i++)
                OnAdd(this, EventArgs.Empty);
        }

        protected override void WndProc(ref Message m) {
            base.WndProc(ref m);
            // Selection of tabs via mouse
            if (m.Msg == 0x201/*WM_LBUTTONDOWN*/) {
                System.Windows.Forms.TabControl control = (System.Windows.Forms.TabControl)Component;
                int lParam = m.LParam.ToInt32();
                Point hitPoint = new Point(lParam & 0xffff, lParam >> 0x10);
                if (Control.FromHandle(m.HWnd) == null) // Navigation
                    if (hitPoint.X < 18 && control.SelectedIndex > 0) // Left
                        control.SelectedIndex--;
                    else control.SelectedIndex++; // Right
                else // Header click
                    for (int i = 0; i < control.TabCount; i++)
                        if (control.GetTabRect(i).Contains(hitPoint)) {
                            control.SelectedIndex = i;
                            return;
                        }
            }
        }

        protected override void OnDragDrop(DragEventArgs de) {
            ((IDropTarget)((System.Windows.Forms.TabControl)Component).SelectedTab).OnDragDrop(de);
        }

        protected override void OnDragEnter(DragEventArgs de) {
            ((IDropTarget)((System.Windows.Forms.TabControl)Component).SelectedTab).OnDragEnter(de);
        }

        protected override void OnDragLeave(EventArgs e) {
            ((IDropTarget)((System.Windows.Forms.TabControl)Component).SelectedTab).OnDragLeave(e);
        }

        protected override void OnDragOver(DragEventArgs de) {
            ((IDropTarget)((System.Windows.Forms.TabControl)Component).SelectedTab).OnDragOver(de);
        }
    }
}

This seems like a quite a complex way, but once you learn it, you will be impressed by powerful capabilites provided by Visual Studio. You can find a lot information in the MSDN. Here are described most common features: Enhancing Design-Time Support

Solution 3

I came across this thread with the same question in mind. After thinking about the problem I realized the solution was staring me in the face. It is actually pretty basic and elegant.

What I did was created a UserControl called TabPageLibrary. Accordingly I dragged a TabControl on it and Added Pages based on the set up I wanted. I then set the TabPage modifier to internal. When I needed a specific extended TabPage - I would simply call the TabPageLibrary class and grab the TabPage I need for a specific application. This gave me the ability to reuse a specific pre-configured TabPage throughout the winform application

private void PropertiesButton_Click(object sender, EventArgs e)
{
TabPageLibrary library = new TabPageLibrary();
TabPage propertyPage = library.PropertyPage;
this.tabControl.TabPages.Add(propertyPage);
}

This certainly solved my problem -- perhaps it will work for your application.

Share:
14,366
ImGreg
Author by

ImGreg

I am a Computer Engineer at the University of Waterloo. CANADA!

Updated on June 12, 2022

Comments

  • ImGreg
    ImGreg almost 2 years

    I have a c# WinForm application that I need to generate TabPages at runtime. Ideally, I would like to design these tabpages using VS designer, but it seems that I can't directly do that as I can't drag and drop it from the toolbox (is there another way?).

    I have two generic tabpages that I will be using multiple times. One that contains a simple spreadsheet and a couple textboxes and another with a graph and a couple textboxes. These pages will eventually get more complicated. I'm looking for the best method of doing this. I am presently just creating custom classes for each tab page and setting it as a TabPage base class. For example:

    public partial class SpreadsheetTabPage : TabPage{} 
    

    I read that user controls offer some form of an alternative, but I don't really understand the advantages of using it vs. my method.

    So to be clear, I want to know what you think is the best approach to developing these custom tabpages and why. Please provide a basic code example if relevant. My method is not really causing too much problems, but I see adding things to these pages later on will be difficult, particularly without use of the designer.

    Thanks for your help in advance!