在进行老旧程序升级的过程中,决定采用当前的标准,并使用MVC(模型-视图-控制器)架构。在浏览CodeProject时,偶然发现了Pritam Zope的文章,它在实现MVC的'V'部分方面做了一些工作,但需要更多功能。
每个标签窗口中的控件都必须能够从标签控制中弹出并返回,无论标签结构的深度如何。此外,每个标签控件都必须能够在停靠或浮动状态下正确执行MVC链接方法。
目标是提高'视觉吸引力',不仅仅是简单的方形标签按钮。需要可变宽度的按钮。
本文将展示所做的改进。
在完全停靠的状态下,标签控件能够正常工作。
在未停靠的状态下,标签控件同样能够正常工作。
此代码完全基于Pritam Zope的工作,因此请参考他的文章了解标签控件是如何实现的。
将控件从一个容器移动到另一个容器非常简单。只需将控件移动到另一个容器,然后从原始位置移除即可。在这段代码中,标签行中的'^'符号将弹出选定的标签到一个浮动窗口。
确保有一个可以弹出的标签。
创建新窗口,设置其标题和标签为拥有的TabControl。
将控件添加到Form.Controls并显示。
从原始位置移除控件。
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中只能有一个控件。这个控件可以是Panel、DataGridView、SplitterContainer或任何可以放置其他控件的容器。
一旦所有内容都配置并测试完毕,就可以像下面展示的那样创建标签页。在这里,可以看到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并将其放置在标签页上,但发现这种方式更容易设计和测试。
通常,视图会接收模型更改事件以更新视图。为了模拟这些事件,实现了一个简单的计时器,该计时器在计时器滴答时更改视图,就好像模型事件被触发了一样。
监视器、连接和数据网格视图无论是在标签页中还是在弹出到窗口中都是活跃的。
尝试将页面弹出并返回到tabcontrol,验证控件无论位于何处都能正常更新。
正如Pritam在评论中提到的,他创建这个演示是为了“从头开始创建自己的tabcontrol”。在看来,方形按钮不符合视觉吸引力要求。所以修改了ButtonX.cs,包括顶部圆角按钮和渐变填充。所有这些都可以根据需要进行自定义。
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
};
// ...
}