如何禁用TabControl中的选项卡?

100
有没有办法禁用 TabControl 中的一个选项卡?

1
我会删除这个标签或者用解释替换它的内容... - Phil1970
27个回答

96

将你的TabPage强制转换为控件(Control),然后将Enabled属性设置为false。

((Control)this.tabPage).Enabled = false;
因此,选项卡页面的标题仍将启用,但其内容将被禁用。

6
我认为这忽略了禁用选项卡本身的意义。用户不能选择它并查看内容。 - ThunderGr
3
也许这是你的使用情况,但我认为它很有用,因为有些权限需要使选项卡只读。 - Cédric Guillemette
10
为什么需要将TabPage向下转换为Control?由于多态性,我们可以从TabPage中调用Enabled属性。 - Eldar Agalarov
2
不确定以前是否有所不同,但今天它完全是胡说八道。69个点赞者都错了。哎呀。。 - TaW
2
不需要进行强制类型转换。当然,选项卡并没有被禁用,它仍然可以被选择。 - TaW
显示剩余6条评论

88

TabPage 类隐藏了 Enabled 属性。这是有意为之的,因为它存在着一些奇怪的 UI 设计问题。基本问题在于,禁用页面并不能同时禁用选项卡。如果您尝试通过在 Selecting 事件中禁用选项卡来解决该问题,则在 TabControl 只有一个页面时无法正常工作。

如果您不关心这些可用性问题,则请记住该属性仍然可以使用,只是在 IntelliSense 中被隐藏了。如果 FUD 让您感到不适,请使用以下方法:

public static void EnableTab(TabPage page, bool enable) {
    foreach (Control ctl in page.Controls) ctl.Enabled = enable;
}

6
我想知道不允许切换选项卡可见性的背后原因是什么。 - Shashank Shekhar
谢谢您的解释,这个解决方案更好。 - Edward Zhang

79

你可以简单地使用:

tabPage.Enabled = false;

虽然不会显示这个属性,但它可以正常运作。

您可以在 TabControler 上编写选择事件,以使其无法切换到不可编辑的选项卡:

private void tabControler_Selecting(object sender, TabControlCancelEventArgs e)
{
    if (e.TabPageIndex < 0) return;
    e.Cancel = !e.TabPage.Enabled;
}

3
太奇怪了... Visible 属性似乎也是如此,尽管在测试时它似乎没有任何视觉效果。 - Alfie
@Alfie 这是因为TabPage继承了以下层次结构:Control > ScrollableControl > Panel > TabPage,Enable、Visible等行为是多态的。 - Master Yoda
运行得很好,为什么它没有显示在向导中? - Edward Zhang

58

你可以注册"Selecting"事件并取消导航到选项卡页面:

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

另一个想法是将标签页中的所有控件放在一个面板控件中,然后禁用该面板!Smiley

您还可以从tabControl1.TabPages集合中删除标签页。这样会隐藏标签页。

感谢littleguru @ Channel 9提供的帮助。


1
更完整的帖子,这才是我应该发布的 :) - Martijn Laarman
2
这是一个非常出色的解决方案!! - Cornelius

14

假设您想在选项卡控件中看到该选项卡,但希望它处于“禁用”状态(即灰色且不可选择)。没有内置支持此功能,但您可以覆盖绘制机制以实现所需的效果。

这里提供了一个示例(链接)说明如何完成这个过程。

关键在于此源代码片段和DisableTab_DrawItem方法:

this.tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
this.tabControl1.DrawItem += new DrawItemEventHandler( DisableTab_DrawItem );

1
示例链接现在似乎已经失效。 - Narthring
1
@Narthring - 谢谢,我已经用一个可用的链接替换了它。 - Stewart
2
@Narthring 它又挂了。 - Sukasa
这是这个问题的“真正”答案。有一个来自waybackmachine的死链接记录:[https://web.archive.org/web/20131102065816/http://tutorials.csharp-online.net/Disabling_Tab_Pages]。 - Joe Uhren
1
这个答案的一个改进是...为每个选项卡添加EnabledChanged事件处理程序,并让事件处理程序在选项卡控件上调用Invalidate(),这样文本颜色就会自动更新。 - ulatekh

13

在扩展Cédric Guillemette的回答之后,当你禁用Control时:

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

你可以像这样处理TabControlSelecting事件:

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

通过这种方式,TabPage上的控件被禁用,但TabPage仍然可选择。 - Syed Irfan Ahmad
1
@SyedIrfanAhmad 这个答案已经快10年了,但它仍然可以正确地工作。如果你遇到了问题,可以发布一个问题。 - rfmodulator
1
你是对的 @rfmodulator,我刚意识到自己漏掉了你关于处理 "Selecting" 事件的第二部分回答。我刚测试过它,它正在工作... - Syed Irfan Ahmad
@SyedIrfanAhmad 但是Lecsox的答案更好。 - rfmodulator

8
这将删除选项卡页,但当您需要它时,您需要重新添加它:
tabControl1.Controls.Remove(tabPage2);

如果您以后需要,可能希望在删除之前将其存储在临时选项卡中,然后在需要时重新添加它。


我认为当您希望在窗体的加载事件中检查用户是否有资格访问此选项卡时,它可以完美地工作,如果没有资格,则将其全部删除。 - ThunderGr
这正好做到了我需要的,即使我想稍后回来将其添加回用户体验中,也可以使选项卡不可见,这是一个完美的解决方案,适用于当您不想从项目中完全删除选项卡时。 - J_L

6
唯一的方法是捕获 Selecting 事件并阻止选项卡被激活。

3
最棘手的方法是使其父级等于null(使标签单独没有父级):
 tabPage.Parent = null;

当您想将其返回时(将在页面集合的末尾将其返回):

tabPage.Parent = tabControl;

如果您想将其返回到页面中特定的位置,则可以使用以下方法:

tabControl.TabPages.Insert(indexLocationYouWant, tabPage);

1
它工作得很好! :)..我有一个问题。当我们将其返回到TabControl时,它会添加最终索引。如何在初始阶段将TabPage添加到相同的索引处。 - User6667769
3
如果您想将其放回到您想要的位置(而不是末尾),请使用以下代码: tabControl.TabPages.Insert(indexLocationYouWant, tabPage); - Amr Ashraf
2
感谢你的回答 @Amr Ashraf - User6667769
这不是禁用页面,而是删除页面。 - Sod Almighty
1
虽然它涉及页面删除,而OP要求禁用它,但最初我也希望禁用页面,但我意识到根据上下文删除和添加页面比启用或禁用它们更有益于用户体验。只需小心不要在事件处理中多次添加相同的页面即可。 - Marcelo Scofano Diniz

1

我以前处理过这个问题。我从TabPages集合中移除了Tab(我想是这样),并在条件改变时重新添加它。但那只是在Winforms中,我可以将选项卡保留到再次需要它的时候。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接