65.9K
CodeProject 正在变化。 阅读更多。
Home

具有弹出窗口的 TabControl

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (5投票s)

2018 年 5 月 5 日

CPOL

3分钟阅读

viewsIcon

16528

downloadIcon

991

本文介绍实现带有弹出窗口的选项卡控件的代码

引言

首先,此代码基于 Pritam Zope 开发的代码,可以在此处找到。

我只是添加了我需要在我的应用程序中使用的 tab control 的功能。

背景

我有一个旧程序,我决定将其升级到当前标准并使用 MVC 架构。 在浏览 CodeProject 时,我遇到了 Pritam 的文章,它做了一些我需要在 MVC 的“V”部分做的事情。 但是,我需要更多。

  1. 无论选项卡结构有多深,选项卡窗口中的每个控件都必须能够弹出并返回到选项卡控件。
  2. 显示每个 tab control 都可以使用停靠或浮动状态下的 MVC 链接方法正常运行。
  3. 拥有比普通方形选项卡按钮更高的“视觉糖果”因素。
  4. 可变宽度按钮。

本文介绍了我想出的内容。

选项卡完全停靠

选项卡未停靠

Using the Code

同样,此代码完全基于 Pritam Zope 所做的工作,因此请参阅他的文章,了解 tab control 的实现方式。

弹出窗口

将控件从一个容器移动到另一个容器非常简单。 只是将控件移动到另一个容器,然后将其从原始位置移除。 在此代码中,选项卡行中的“^”符号会将选定的选项卡弹出到浮动窗口。

  1. 确保有一个选项卡可以弹出
  2. 创建新窗口,将其标题和 Tag 设置为拥有的 TabControl
  3. 将控件添加到 Form.Controls 并显示
  4. 从原始位置移除控件
        private void toolStripLabel1_Click(object sender, EventArgs e)
        {
            if (_selectedIndex < 0) return;
            var frm = new FormTab
            {
                Text = _buttonlist[_selectedIndex].DisplayText,
                Tag = this
            };
            frm.Controls.Add(_tabPanelCtrlList[_selectedIndex]);
            frm.Show();
            RemoveTab(_selectedIndex);
        }

反转此过程会将控件返回到选项卡结构。 在 FormTab.cs 中,您会发现

        private void FormTab_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (Tag.GetType() != typeof(TabControlX)) return;
            var tc = (TabControlX)Tag;
            var tpc = new TabPanelControl { Dock = DockStyle.Fill };
            tpc.Controls.Add(Controls[0]);
            tc.AddTab(Text, tpc);
        }

我使用 Form 设计我的控件,但 Form.Controls 中必须只有一个控件。 此控件可以是 PanelDataGridViewSplitterContainer 或您可以将其他控件放入其中的任何东西。 对于此演示,FormMonitorFormConnection 中的顶级控件是 Panel,其他控件放置在面板内。

在表单中配置和测试所有内容后,它可用于创建选项卡页面,如下所示。 在这里,我们看到 FormConnection 被实例化,并且它的顶级控件被移动到选项卡页面。 单击窗口上的关闭框将取消弹出它。

    private void button4_Click(object sender, EventArgs e)
        {
            var tpc = new TabPanelControl();
            var conn = new FormConnection();
            tpc.Controls.Add(conn.Controls[0]);
            tabControlX1.AddTab(conn.Text, tpc);
            .
            .
            .
        }

是的,我可以将这些控件开发为 UserControl 并将它们放到选项卡页面上,但我只是觉得这样设计和测试更容易。

MVC 链接

通常,视图获取更新视图的模型更改事件。 为了模拟这些事件,我只是实现了一个简单的计时器,它在计时器滴答声时更改视图,就好像触发了模型事件一样。 MonitorConnectionsDataGrid 视图无论是在选项卡页面中还是弹出到窗口中都是活动的。

尝试通过弹出和关闭 tabcontrol 上的页面来试用它。 验证控件是否仍在更新,无论它们位于何处。

视觉糖果因素

正如 Pritam 在其中一条评论中所述,他创建了这个演示来“从头开始创建自己的 tabcontrol”。 我认为,用于选项卡的方形按钮只是不符合我的视觉糖果因素要求。 所以我继续修改了 ButtonX.cs 以包括带有渐变填充的顶部圆形按钮。 所有这些都可以根据您的需要进行自定义。

可变宽度按钮

我不喜欢固定的按钮宽度,因此我在 TabControlX.cs 中的 CreateAndAddButton 函数中添加了以下代码。 基本上,它创建了一个设备上下文句柄,并使用 TextRender.MeasureText 来计算使按钮包含文本的宽度。

        private void CreateAndAddButton(string tabtext, TabPanelControl tpcontrol, Point loc)
        {
            var dc = CreateGraphics();
            var t = TextRenderer.MeasureText(dc, tabtext, Font);
            var bx = new ButtonX
            {
                DisplayText = tabtext,
                Text = tabtext,
                Size = new Size(t.Width + 20, 30),
                Location = loc,
                TextLocationX = 10,
                TextLocationY = 9,
                Font = Font
            };
            .
            .
            .

历史

  • 2018 年 5 月 5 日:初始版本
© . All rights reserved.