100

Is there a way to disable a tab in a TabControl?

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
Gold
  • 60,526
  • 100
  • 215
  • 315

27 Answers27

96

Cast your TabPage to a Control, then set the Enabled property to false.

((Control)this.tabPage).Enabled = false;

Therefore, the tabpage's header will still be enabled but its contents will be disabled.

TheCloudlessSky
  • 18,608
  • 15
  • 75
  • 116
Cédric Guillemette
  • 2,394
  • 1
  • 14
  • 22
  • 6
    I think this misses the point of disabling the tab, itself. The user is not supposed to be able to select it and see the contents. – ThunderGr Oct 19 '12 at 10:18
  • 3
    That may be your use case but I think its useful if the tab needs to be read-only because of some rights. – Cédric Guillemette Nov 29 '12 at 13:27
  • 10
    Why need downcasting TabPage to Control? We can invoke Enabled property from TabPage due to polymorphism. – Eldar Agalarov Aug 12 '13 at 22:44
  • 2
    Not sure if it ever was different but today it is utter nonsense. 69 upvoters in the wrong. Ouch.. – TaW May 26 '16 at 13:03
  • 1
    @TaW This question specifically and concisely answers the question. "Is there any way to disable a tab in a tabcontrol?" They don't ask how to hide a tab. 69 upvoters in the right... 1 commenter that didn't read the question in the wrong. Ouch... – DDuffy Jun 02 '16 at 12:24
  • 2
    No. The cast was and is unnecessary. And of course the TabPage is not disbled at all: It can be selected. – TaW Jun 02 '16 at 13:21
  • 1
    If you take the battery out of your car, you have disabled it. You can still see it, you can still touch it, you just cant use it. Disabling and hiding are two very different things. – DDuffy Sep 08 '16 at 11:37
  • 1
    There is a difference between disabling a *tab* and disabling the *contents* of its *page*. This answer is wrong, and 93 people are also wrong. – Sod Almighty Jul 30 '21 at 21:35
  • Also, as others have pointed out, the downcast is redundant. – Sod Almighty Jul 30 '21 at 21:39
  • With this, controls on the TabPage are disabled but TabPage remains selectable – Syed Irfan Ahmad Mar 07 '22 at 12:08
  • I don't think a TabPage can be disabled. Even Microsoft [documentation](https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/how-to-disable-tab-pages) has used alternative technique to restrict access to an unwanted TabPage. – Syed Irfan Ahmad Mar 07 '22 at 12:12
87

The TabPage class hides the Enabled property. That was intentional as there is an awkward UI design problem with it. The basic issue is that disabling the page does not also disable the tab. And if try to work around that by disabling the tab with the Selecting event then it does not work when the TabControl has only one page.

If these usability problems do not concern you then keep in mind that the property still works, it is merely hidden from IntelliSense. If the FUD is uncomfortable then you can simply do this:

public static void EnableTab(TabPage page, bool enable) {
    foreach (Control ctl in page.Controls) ctl.Enabled = enable;
}
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
80

You can simply use:

tabPage.Enabled = false;

This property is not shown, but it works without any problems.

You can program the Selecting event on TabControler to make it impossible to change to a non-editable tab:

private void tabControler_Selecting(object sender, TabControlCancelEventArgs e)
{
    if (e.TabPageIndex < 0) return;
    e.Cancel = !e.TabPage.Enabled;
}
shox
  • 677
  • 1
  • 5
  • 19
Lecsox
  • 961
  • 7
  • 8
  • 3
    How bizarre.. this also seems to be true of the `Visible` property, although it didn't seem to actually have any visual effect when I tested it. – Alfie Sep 16 '13 at 12:13
  • @Alfie Its because TabPage inherits from the following hierarchy: Control > ScrollableControl > Panel > TabPage, the Enable, Visible etc. behaviour is polymorphic. – Master Yoda Apr 28 '15 at 14:46
  • Works like a charm, why it's not shown in the wizard? – Edward Zhang Sep 18 '22 at 08:30
58

You could register the "Selecting" event and cancel the navigation to the tab page:

private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
    if (e.TabPage == tabPage2)
        e.Cancel = true;
}

Another idea is to put all the controls on the tabpage in a Panel control and disable the panel! Smiley

You could also remove the tabpage from the tabControl1.TabPages collection. That would hide the tabpage.

Credits go to littleguru @ Channel 9.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Stormenet
  • 25,926
  • 9
  • 53
  • 65
14

Presumably, you want to see the tab in the tab control, but you want it to be "disabled" (i.e., greyed, and unselectable). There is no built-in support for this, but you can override the drawing mechanism to give the desired effect.

An example of how to do this is provided here.

The magic is in this snippet from the presented source, and in the DisableTab_DrawItem method:

this.tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
this.tabControl1.DrawItem += new DrawItemEventHandler( DisableTab_DrawItem );
John
  • 1,011
  • 11
  • 18
Stewart
  • 4,223
  • 6
  • 31
  • 39
  • 1
    Example link now appears to be dead. – Narthring Nov 01 '12 at 16:29
  • 1
    @Narthring - Thanks, I've substituted the link for a working one. – Stewart Nov 07 '12 at 14:21
  • 2
    @Narthring It's dead again. – Sukasa Feb 21 '14 at 21:32
  • This is the "real" answer to this question. There is a record of the dead link from waybackmachine: [https://web.archive.org/web/20131102065816/http://tutorials.csharp-online.net/Disabling_Tab_Pages]. – Joe Uhren Jan 16 '15 at 03:56
  • One improvement to this answer...add an [EnabledChanged](https://msdn.microsoft.com/en-us/library/system.windows.forms.control.enabledchanged(v=vs.100).aspx) event-handler to each of your tabs, and have the event-handler call [Invalidate()](https://msdn.microsoft.com/en-us/library/598t492a(v=vs.100).aspx) on the tab-control. That way, the text-color will update automatically. – ulatekh Jun 19 '18 at 20:40
13

Extending upon Cédric Guillemette answer, after you disable the Control:

((Control)this.tabPage).Enabled = false;

...you may then handle the TabControl's Selecting event as:

private void tabControl_Selecting(object sender, TabControlCancelEventArgs e)
{
    e.Cancel = !((Control)e.TabPage).Enabled;
}
rfmodulator
  • 3,638
  • 3
  • 18
  • 22
8

This will remove the tab page, but you'll need to re-add it when you need it:

tabControl1.Controls.Remove(tabPage2);

If you are going to need it later, you might want to store it in a temporary tabpage before the remove and then re-add it when needed.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
sahran
  • 89
  • 1
  • 3
  • I think it works perfectly when you wish to check, on the Load event of the form, if the user is eligible to access this tab and if not, just remove it, altogether. – ThunderGr Oct 19 '12 at 10:14
  • This did exactly what I needed which was to get the tab out of visibility unless I want to come back later and add it back to the user experience, perfect solution for when you don't want to remove the tab altogether from the project. – J_L May 07 '21 at 21:35
6

The only way is to catch the Selecting event and prevent a tab from being activated.

Martijn Laarman
  • 13,476
  • 44
  • 63
2

The most tricky way is to make its parent equals null (make the tab alone without parent):

 tabPage.Parent = null;

And when you want to return it back (will return it back at the end of pages collection) :

tabPage.Parent = tabControl;

And if you want to return it back in a specific location among the pages you can use :

tabControl.TabPages.Insert(indexLocationYouWant, tabPage);
Amr Ashraf
  • 419
  • 6
  • 19
  • 1
    Its working good! :)..I have one question. When we return it back to the tabcontrol its adding final index. How to we add the tabpage at the same index from its initial stage. – User6667769 Aug 04 '17 at 08:35
  • 3
    If you want to return it back in a location that you want (not at the end), use: tabControl.TabPages.Insert(indexLocationYouWant, tabPage); – Amr Ashraf Aug 29 '17 at 09:50
  • 2
    Thank you for your answer @Amr Ashraf – User6667769 Aug 29 '17 at 09:55
  • This is not disabling the page, this is *removing* the page. – Sod Almighty Jul 30 '21 at 21:28
  • +1 Although it deals with page removing and OP asked for disabling it, initially I too wished to disable pages, but I realized that user experience benefited much more from removing and adding pages based on context than enabling or disabling them. Just be careful to not add same page more than once on event handling. – Marcelo Scofano Diniz Jul 12 '22 at 01:12
1

I had to handle this a while back. I removed the Tab from the TabPages collection (I think that's it) and added it back in when the conditions changed. But that was only in Winforms where I could keep the tab around until I needed it again.

jcollum
  • 43,623
  • 55
  • 191
  • 321
0

Using events, and the properties of the tab control you can enable/disable what you want when you want. I used one bool that is available to all methods in the mdi child form class where the tabControl is being used.

Remember the selecting event fires every time any tab is clicked. For large numbers of tabs a "CASE" might be easier to use than a bunch of ifs.

public partial class Form2 : Form
    {
        bool formComplete = false;

        public Form2()
        {
            InitializeComponent();

        }

        private void button1_Click(object sender, EventArgs e)
        {


            formComplete = true;
            tabControl1.SelectTab(1);

        }

        private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
        {
            if (tabControl1.SelectedTab == tabControl1.TabPages[1])
            {

                tabControl1.Enabled = false;

                if (formComplete)
                {
                    MessageBox.Show("You will be taken to next tab");
                    tabControl1.SelectTab(1);

                }
                else
                {
                    MessageBox.Show("Try completing form first");
                    tabControl1.SelectTab(0);
                }
                tabControl1.Enabled = true;
            }
        }
    }
KWB Tech
  • 1
  • 1
0

The user cannot click on tabs to navigate, but they can use the two buttons (Next and Back). The user cannot continue to the next if the //conditions are no met.

private int currentTab = 0;

private void frmOneTimeEntry_Load(object sender, EventArgs e)
{
    tabMenu.Selecting += new TabControlCancelEventHandler(tabMenu_Selecting);
}

private void tabMenu_Selecting(object sender, TabControlCancelEventArgs e)
{
    tabMenu.SelectTab(currentTab);
}

private void btnNextStep_Click(object sender, EventArgs e)
{
    switch(tabMenu.SelectedIndex)
    {
        case 0:
            //if conditions met GoTo
        case 2:
            //if conditions met GoTo
        case n:
            //if conditions met GoTo
    {
    CanLeaveTab:
    currentTab++;
    tabMenu.SelectTab(tabMenu.SelectedIndex + 1);
    if (tabMenu.SelectedIndex == 3)
        btnNextStep.Enabled = false;
    if (btnBackStep.Enabled == false)
        btnBackStep.Enabled = true;

    CannotLeaveTab:
        ;
}

private void btnBackStep_Click(object sender, EventArgs e)
{
    currentTab--;
    tabMenu.SelectTab(tabMenu.SelectedIndex - 1);
    if (tabMenu.SelectedIndex == 0)
        btnBackStep.Enabled = false;
    if (btnNextStep.Enabled == false)
        btnNextStep.Enabled = true;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
kennedy484
  • 455
  • 1
  • 5
  • 11
0

I've solved this problem like this: I've got 3 tabs and I want to keep user at the first tab if he didnt log in, so on the SelectingEvent of TabControl I wrote

if (condition) { TabControl.Deselect("2ndPage"); TabControl.Deselect("3dPage"); }
Orkhan M.
  • 143
  • 1
  • 11
0

tabControl.TabPages.Remove(tabPage1);

0

I've removed tab pages in the past to prevent the user from clicking them. This probably isn't the best solution though because they may need to see that the tab page exists.

Aaron Smith
  • 3,332
  • 4
  • 29
  • 25
0

This is an old question, but someone may benefit from my addition. I needed a TabControl that would show hidden tabs successively (after an action was performed on the current tab). So, I made a quick class to inherit from and called HideSuccessive() on Load:

public class RevealingTabControl : TabControl
{
    private Action _showNextRequested = delegate { };

    public void HideSuccessive()
    {
        var tabPages = this.TabPages.Cast<TabPage>().Skip(1);
        var queue = new ConcurrentQueue<TabPage>(tabPages);
        tabPages.ToList().ForEach(t => t.Parent = null);
        _showNextRequested = () =>
        {
            if (queue.TryDequeue(out TabPage tabPage))
                tabPage.Parent = this;
        };
    }

    public void ShowNext() => _showNextRequested();
}
Ryan Naccarato
  • 674
  • 8
  • 12
0

There is the XtraTabPage.PageEnabled property allowing you to disable certain pages.

Vlad Gonchar
  • 495
  • 4
  • 5
0

Here the solution that i implement:

   private void switchTapPage(TabPage tabPage)
    {
        
        foreach(TabPage page in tabControl1.TabPages)
        {
            tabControl1.TabPages.Remove(page);
        }

        tabControl1.TabPages.Add(tabPage);
    }

Basically, i just call this method sending the tabPage that i currently need to show, the method will remove all the tabPages on the tabControl and after that it will just add the one that i sent it.

So the rest of the tabHeaders will not shown and they will be inaccessible, because they dont even exists in the tabControl.

I took the idea from the @stormenet answer.

JuulFan
  • 21
  • 7
0

I'm using the following code to disable the tab page with index 2 and to switch the focus to the tab page index 0.

    private void tabControl1_Selected(object sender, TabControlEventArgs e) {
        if( 2 == e.TabPageIndex) 
            tabControl1.SelectedIndex = 0;
    }
SPirev
  • 21
  • 2
-1

You can do it through the tabpages: tabPage1.Hide(), tabPage2.Show() etc.

aldebaran
  • 695
  • 8
  • 20
-1

In the form load event if we write this.tabpage.PageEnabled = false, the tabpage will be disabled.

Felipe Oriani
  • 37,948
  • 19
  • 131
  • 194
New
  • 675
  • 1
  • 11
  • 21
  • Cannot see that Property – John May 16 '15 at 11:38
  • please check whether you tried it in the load event of the form ? – New May 19 '15 at 05:08
  • Just doubled checked now. Cannot see it. – John May 19 '15 at 08:26
  • please check whether you used this : private void XtraForm1_Load(object sender, EventArgs e) { this.xtraTabPage1.PageEnabled = false; } the XtraForm1 is the DevExpress XtraForm and the tabpage xtraTabPage is DevExpress XtraTabpage – New May 20 '15 at 05:58
  • Why didn't you say anything about DevExpress in your original answer...? – John May 20 '15 at 10:13
-1

Assume that you have these controls:

TabControl with name tcExemple.

TabPages with names tpEx1 and tpEx2.

Try it:

Set DrawMode of your TabPage to OwnerDrawFixed; After InitializeComponent(), make sure that tpEx2 is not enable by adding this code:

((Control)tcExemple.TabPages["tpEx2").Enabled = false;

Add to Selection tcExemple event the code below:

private void tcExemple_Selecting(object sender, TabControlCancelEventArgs e)
    {
        if (!((Control)e.TabPage).Enabled)
        {
            e.Cancel = true;
        }
    }

Attach to DrawItem event of tcExemple this code:

private void tcExemple_DrawItem(object sender, DrawItemEventArgs e)
    {
        TabPage page = tcExemple.TabPages[e.Index];
        if (!((Control)page).Enabled)
        {
            using (SolidBrush brush = new SolidBrush(SystemColors.GrayText))
            {
                e.Graphics.DrawString(page.Text, page.Font, brush, e.Bounds);
            }
        }
        else
        {
            using (SolidBrush brush = new SolidBrush(page.ForeColor))
            {
                e.Graphics.DrawString(page.Text, page.Font, brush, e.Bounds);
            }
        }
    }

It will make the second tab non-clickable.

Rafael
  • 966
  • 12
  • 22
  • Yeah, but you're using `DrawString`, which makes the tab test look noticeably different to standard tab controls. What you want there is `TextRenderer`. – Sod Almighty Jul 30 '21 at 21:30
-1

I could not find an appropriate answer to the question. There looks to be no solution to disable the specific tab. What I did is to pass the specific tab to a variable and in SelectedIndexChanged event put it back to SelectedIndex:

//variable for your specific tab 
int _TAB = 0;

//here you specify your tab that you want to expose
_TAB = 1;
tabHolder.SelectedIndex = _TAB;

private void tabHolder_SelectedIndexChanged(object sender, EventArgs e)
{
    if (_TAB != 0) tabHolder.SelectedIndex = _TAB;
}

So, you don't actually disable the tab, but when another tab is clicked it always returns you to the selected tab.

Ray Krungkaew
  • 6,652
  • 1
  • 17
  • 28
Andy
  • 1
-1

in C# 7.0, there is a new feature called Pattern Matching. You can disable all tabs via Type Pattern.

foreach (Control control in Controls)
{
    // the is expression tests the variable and 
    // assigned it to a new appropriate variable type
    if (control is TabControl tabs)
    {
        tabs.Enabled = false;
    }
}
Umut D.
  • 1,746
  • 23
  • 24
-2

Use:

 tabControl1.TabPages[1].Enabled = false;

By writing this code, the tab page won't be completely disabled (not being able to select), but its internal content will be disabled which I think satisfy your needs.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Code_Worm
  • 4,069
  • 2
  • 30
  • 35
-2

The solution is very simple.

Remove/comment this line

this.tabControl.Controls.Add(this.YourTabName);

in IntializeComponent() method in MainForm.cs

-4
MyTabControl.SelectedTab.Enabled = false;
bluish
  • 26,356
  • 27
  • 122
  • 180
jay_t55
  • 11,362
  • 28
  • 103
  • 174