在C#的TabControl中隐藏选项卡标题头

53

我正在开发一个包含多个页面的 Windows Form 应用程序。我使用 TabControl 来实现这一点。但是,我希望我的应用程序来控制选项卡之间的切换,例如在用户填写文本框并单击下一步按钮后,下一个选项卡应该打开。


1
@Plutonix: 因为在设计师中,通过切换选项卡来切换不同的小部件组会更加容易。 - Dan W
myPanelTabs(n).BringToFront 完成。或者更改可见性。 - Ňɏssa Pøngjǣrdenlarp
2
@Plutonix:虽然这是代码,但我想在表单设计器中单击一次即可切换给定区域中的内容。 - Dan W
@MickyDuncan: 对于用户来说,程序看起来绝对不像是一个向导。根据他们选择的软件版本,他们只能看到其中一个标签页,其他的标签页/页面将永久无法访问,因为它们是无关的。但是没错,开发者可以利用这个想法来实现类似向导的系统。 - Dan W
@MickyDuncan: 你是指 DesignMode 吧?虽然可以创建一个 UserControl,但这将取消标准 TabControl 提供的功能,所以我猜这样的答案可能会非常复杂。如果你认为编码很简单,那么请添加一个答案(不过,除非它也解决了赏金问题,否则这样的答案与我提供的赏金无关)。 - Dan W
显示剩余2条评论
10个回答

108

在您的项目中添加一个新类,并粘贴下面显示的代码。编译。从工具箱的顶部将新控件拖放到表单上。它在设计时显示选项卡,因此您可以在设计时轻松地在它们之间切换。它们在运行时被隐藏,使用SelectedTab或SelectedIndex属性在您的代码中切换页面。

using System;
using System.Windows.Forms;

public class TablessControl : TabControl {
  protected override void WndProc(ref Message m) {
    // Hide tabs by trapping the TCM_ADJUSTRECT message
    if (m.Msg == 0x1328 && !DesignMode) m.Result = (IntPtr)1;
    else base.WndProc(ref m);
  }
}

22
这不是一个观点。在所有的Windows版本中都能够良好运作。 - Hans Passant
4
你好,你能否更新你的代码以处理左/右箭头也消失的情况?(当标签页超出 StackPanel 盒子所能容纳的数量时,它们会显示)。非常感谢;能够像这样轻松切换视图非常方便。 - Dan W
1
请将您的示例从 class TablessControl 编辑为 public class TablessControl,以便在使用不同程序集时在工具箱中显示它。 - Nebula
2
请解释一下这个答案中的代码! - Lii
2
我认为您也想在此类中重写OnKeyDown方法以过滤掉Ctrl+Tab事件。如果(ke.KeyCode == Keys.Tab && ke.Control)... - Eric Hirst
显示剩余9条评论

39
tabControl1.Appearance = TabAppearance.FlatButtons;
tabControl1.ItemSize = new Size(0, 1);
tabControl1.SizeMode = TabSizeMode.Fixed;

避免仅提供代码的答案。添加一些关于您解决方案的描述。 - ughai
1
那绝对是最简单的方法,对我来说效果很好。如果你愿意,你可以在设计师属性中完成它。 - dmihailescu
避免创建新的继承控件的解决方案。做得好。 - Daniel
很遗憾,这个最佳的答案背后没有任何解释。你可以在设计器属性中设置所有内容,只需在“PageLoad”上设置“ItemSize”。在我看来,这应该是最好的答案。不过,微软应该将此功能作为一个选项提供。 - krowe2
2
另外,您可能希望使用 tabControl1.TabStop = False; - krowe2

16

创建新的UserControl,例如命名为TabControlWithoutHeader,并将继承的UserControl更改为TabControl并添加一些代码。结果代码应如下所示:

public partial class TabControlWithoutHeader: TabControl
{
    public TabControlWithoutHeader()
    {
        InitializeComponent();
    }

    protected override void WndProc(ref Message m)
    {
    if (m.Msg == 0x1328 && !DesignMode)
        m.Result = (IntPtr)1;
    else
        base.WndProc(ref m);
    }
}
编译后,您将在工具箱中拥有TabControlWithoutHeader控件。将其拖放到表单上,在设计器中您将看到页签标题,但在运行时它们将被隐藏。如果您想在设计器中也隐藏它们,则删除&& !DesignMode。希望能帮到您。 参考链接:http://social.msdn.microsoft.com/Forums/windows/en-US/c290832f-3b84-4200-aa4a-7a5dc4b8b5bb/tabs-in-winform?forum=winforms

1
在 SO 上需要署名。 - Hans Passant
2
@Hans 抱歉,我不理解你写的内容。 - Renatas M.
Hans说他已经发布了这个答案。你只是复制并再次发布了它。 - Cody Gray
@volody Hans在MSDN上发布了这篇文章(使用他的MSDN用户名Nobugz)2007年... - Matthew Watson
1
好的,我不是一个巫师,无法知道原始代码的创建者,特别是在不同的网站下隐藏的人。所以感谢@MatthewWatson解释了其他人在谈论什么。 :) - Renatas M.

13

您可以使用手工制作的面板来替换TabControl,使其外观与您想要的类似:

class MultiPagePanel : Panel
{
  private int _currentPageIndex;
  public int CurrentPageIndex
  {
    get { return _currentPageIndex; }
    set
    {
      if (value >= 0 && value < Controls.Count)
      {
        Controls[value].BringToFront();
        _currentPageIndex = value;
      }
    }
  }

  public void AddPage(Control page)
  {
    Controls.Add(page);
    page.Dock = DockStyle.Fill;
  }
}

然后添加页面并设置当前可见页面:

MultiPagePanel p;

// MyTabPage is a Control derived class that represents one page on your form.
MyTabPage page = new MyTabPage(); 
p.AddPage(page);

p.CurrentPageIndex = 0;

2
刚刚偶然看到这个帖子,发现一个错误:if (value >= 0 && value < (Controls.Count - 1)) 应该改为 if (value >= 0 && value < Controls.Count),否则会漏掉一些面板。 - benst

10

我需要这段代码,但是它是用VB.net编写的,所以我将其转换了。如果有人需要VB.Net版本的这段代码,那就在这里了。

Imports System
Imports System.Windows.Forms

Public Class TablessControl
           Inherits System.Windows.Forms.TabControl

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        ' Hide tabs by trapping the TCM_ADJUSTRECT message
        If (m.Msg = Convert.ToInt32("0x1328", 16) And Not DesignMode) Then
            m.Result = CType(1, IntPtr)
        Else
            MyBase.WndProc(m)
        End If
    End Sub

End Class

特别感谢 @Hans Passant 在 C# 中提供的答案。


有趣的想法。这是你在VB.NET中描述的解决方案的C#版本:https://blog.laplante.io/2011/01/hiding-tab-headers-on-a-tabcontrol-in-c/ - Matt

6
为了补充 Hans Passant 的现有答案,我找到了四种方法来在选项卡的数量超过 TablessControl 的宽度时隐藏箭头。没有一种单一的解决方案适合所有人,但可能适合您(或者至少是它们的组合)。
解决方案1:
只需启用 Multiline。这将防止箭头出现。但是,请注意,在设计师中,您可能会失去所见即所得,因为垂直空间会向下调整,并且 TablessControl 中的控件甚至可能在底部被“切断”(尽管仅在开发者模式下)。
解决方案2:
更高级的解决方案解决了上述的所见即所得问题,即只有在程序运行时才启用 Multiline。只需将此构造函数添加到 TablessControl 类中:
public TablessControl()
{
    bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
    if (!designMode) Multiline = true;      
}

对于开发人员来说,它们仍将显示为单行选项卡。

解决方案3:

减小TablessControl的字体大小。每个选项卡应相应缩小。由于用户永远不会看到选项卡,因此将字体大小设置为甚至为4pt应该不会有太大影响。

但是要注意,TablessControl的内容也可能被调整大小。如果出现这种情况,请重新编辑每个部件内的字体大小,然后,即使您随后再次决定重新更改主TablessControl的字体大小,它们也将幸运地保持在那个大小。

这种方法还具有更接近真正WYSIWYG垂直可用空间的优点,这样即使在设计师中由于选项卡的高度而在底部略微被削减,对于用户看起来也很好。

此解决方案可以与解决方案1和2结合使用以累积优势。

解决方案4:

如果任何选项卡的文本都很长,则此解决方案并不一定那么好。感谢Hans提出此建议。

首先将TablessControl的SizeMode设置为“固定”,然后减少TablessControl的ItemSize Width属性以减小每个选项卡的宽度。也可以自由地调整ItemSize Height属性以帮助解决上述WYSIWYG问题,但是解决方案3可能更有帮助。

此解决方案可与以上解决方案结合使用以进一步累积优势。


4
如果你真的想做这件事,你可以像这样做。
 tcActionControls.Region = new Region(new RectangleF(
             tbPageToShow.Left, 
               tbPageToShow.Top, 
                 tbPageToShow.Width, 
                    tbPageToShow.Height)
);

这应该能满足您的需求: tcActionControls 是您的 TabControl,而 tbPageToShow 则是此时要显示的 TabPage

应该可以为您工作。

祝好。


2
这个解决方案似乎很好 - 如何隐藏选项卡控件中的选项卡?
  1. 将TabControl插入到表单中,默认名称为TabControl1。

  2. 确保在Visual Studio的属性窗格中选择TabControl1并更改以下属性:

    a. 将Appearance设置为Buttons

    b. 将ItemSize的宽度设置为0,高度设置为1

    c. 将Multiline设置为True

    d. 将SizeMode设置为Fixed

最好在完成设计时任务后再执行此操作,因为它还会将它们隐藏在设计器中 - 这使得导航变得困难!


0
你可以尝试从TabPageCollection中移除TabPage:
TabControl.TabPageCollection tabCol = tabControl1.TabPages;
        foreach (TabPage tp in tabCol)
        {
           if(condition)
            { 
              tabCol.Remove(tp);
            }
        }

问题是关于删除可见选项卡内容顶部的标题行(包含选项卡名称)。这不是对该问题的回答。 - ToolmakerSteve
tabControl.Appearance = TabAppearance.FlatButtons; tabControl.ItemSize = new Size(0, 1); tabControl.SizeMode = TabSizeMode.Fixed; foreach (TabPage tab in tabControl.TabPages) { tab.Text = ""; } - marz

0
在我的WinForms应用程序中,我能够通过将TabControl的y坐标定位在窗体的可见范围之外来解决这个问题,因此选项卡实际上被隐藏了。这个例子只适用于tabControl靠近窗体顶部的情况,但你可以理解这个思路。
private void frmOptions_Load(object sender, EventArgs e)
{
    tabControl1.Top = -23; //Only tabPage contents visible
}

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