根据 TabPages 的数量动态调整 TabControl 和 Form 的宽度
Dynamically resize TabControl and Form width to the number of TabPages
我有一个带有 TabControl 和 ListView 的 windows 表单。
当我 运行 应用程序时,我希望 TabControl 的 Width
到 increase/decrease 显示所有没有水平滚动条的 TabPages 并相应地调整表单的大小 Width
,以确保TabControl 和 ListView 可见。
下面是截图。
从该表格开始,我将在 运行 时添加 8 个标签,计算标签中文本的宽度 + 填充大小 x2(标签的两侧),然后调整大小根据需要进行控制。
public Form1()
{
InitializeComponent();
//Clear our default tabs.
tabControl1.TabPages.Clear();
//Add more tabs than would be visible by default
for (int i=1;i<=8;i++)
{
tabControl1.TabPages.Add("Tab " + i.ToString());
}
ResizeTabControl();
ResizeListViewControl();
ResizeForm();
}
void ResizeTabControl()
{
int tabCount = tabControl1.TabCount;
float length = 0;
using (Graphics g = CreateGraphics())
{
//Iterate through the tabs and get the length of the text.
for (int i = 0; i <= tabCount - 1; i++)
length += g.MeasureString(tabControl1.TabPages[i].Text, tabControl1.Font).Width;
}
//Resize the tab control where X is the length of all text in the tabs plus padding x 2 x total tabs.
tabControl1.Size = new Size(Convert.ToInt32(length) + (tabCount * 2 * tabControl1.Padding.X), tabControl1.Width);
}
void ResizeListViewControl()
{
//Move listview 10 pixels away from tabcontrol's edge
listView1.Location = new Point(tabControl1.Location.X + tabControl1.Width + 10, listView1.Location.Y);
}
void ResizeForm()
{
//Resize form to accomodate changes.
this.Width = listView1.Location.X + listView1.Width + 20;
}
说完一切后,这就是它的样子:
还有 20 个标签,因为为什么不呢。
要auto-size一个TabControl到它的Headers的大小,你需要计算每个Header的文本宽度。如果 TabControl.SizeMode is set to Fixed, since you can set the ItemSize.Width 和所有 Header 具有相同的宽度,则更简单。
如果TabControl.SizeMode
设置为默认Normal
,则必须测量每个Header的Text,为边框添加1px
(2px
如果它是第二个 TabPage - 基本控件中的小 bug)。
第一种情况,TabControl的大小为:
tabControl1.Width = tabControl1.TabPages.Count * (tabControl1.ItemSize.Width + 1);
在第二种情况下,使用TextRendrer.MeasureText测量每个Header的文本:
private int MeasureTabPagesWidth(TabControl tc)
{
if (tc.TabPages.Count == 0) return tc.Width;
int newWidth = 0;
int border = tc.TabPages.Count == 2 ? 2 : 1;
var flags = TextFormatFlags.LeftAndRightPadding;
using (var g = tc.CreateGraphics()) {
foreach (TabPage tab in tc.TabPages) {
newWidth += TextRenderer.MeasureText(g, tab.Text, tc.Font,
new Size(int.MaxValue, tc.Font.Height + 4), flags).Width + border;
}
}
return newWidth;
}
设置布局:
- 向您的表单添加一个 TableLayoutPanel,具有一行和两列(即,删除一行)
- 将 TabControl 添加到左侧的 Cell,将 ListBox 添加到另一个 Cell。
- 将两个单元格的样式设置为
AutoSize
(在 添加控件后)。
- 将 TableLayoutPanel 设置为:
AutoSize = true
、AutoSizeMode
= GrowAndShrink
- 同样的方法将Form设置为auto-size
- 将表格的 MinimumSize and MaximumSize. The former is usually set to the design size, the latter is up to you; you could use the current Screen WorkingArea 设置为参考。
- 在创建或加载窗体时(即在其构造函数或
OnLoad()
或Form.Load
中)计算TabControl的新宽度,因此窗体将auto-size到TableLayoutPanel 的大小,依次 auto-size 到其 child 控件的大小。
现在您可以在 run-time 添加或删除 TabPages 并且表单将 auto-size 到您在 TabControl.ControlAdded and TabControl.ControlRemoved 事件处理程序中计算的宽度(同时检查添加的控件是否是输入 TabPage
).
例子:
MeasureTabPagesWidth()
方法就是上面的那个
- TableLayoutPanel 名为
tlp1
- TabControl 名为
tabControl1
- 视觉示例中使用的按钮具有定义其作用的名称。
public partial class AutoSizeForm : Form
{
public AutoSizeForm()
{
InitializeComponent();
tabControl1.Width = MeasureTabPagesWidth(tabControl1);
}
private void tabControl1_ControlAdded(object sender, ControlEventArgs e)
{
// Event notified after the TabPage has been added
if (e.Control is TabPage) {
tabControl1.Width = MeasureTabPagesWidth(tabControl1);
}
}
private void tabControl1_ControlRemoved(object sender, ControlEventArgs e)
{
if (e.Control is TabPage) {
// Use deferred execution, since the TabPage is removed after
// the event handler method completes.
BeginInvoke(new Action(()=> tabControl1.Width = MeasureTabPagesWidth(tabControl1)));
}
}
private void btnAddPage_Click(object sender, EventArgs e)
{
tabControl1.TabPages.Add(new TabPage("New TabpPage Text"));
}
private void btnRemovePage_Click(object sender, EventArgs e)
{
if (tabControl1.TabPages.Count > 0) {
tabControl1.TabPages.RemoveAt(tabControl1.TabPages.Count - 1);
}
}
private void btnAddCtlToTLP_Click(object sender, EventArgs e)
{
tlp1.ColumnCount += 1;
tlp1.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
var mc = new MonthCalendar();
tlp1.SetColumn(mc, tlp1.ColumnCount - 1);
tlp1.Controls.Add(mc);
}
}
它是这样工作的:
在 Windows 7 中测试,因为这似乎是正在使用的系统
示例项目:
Sample Project on Google Drive (.Net Framework 4.8
- C# 7.3
)
在 运行
之前重建解决方案
我有一个带有 TabControl 和 ListView 的 windows 表单。
当我 运行 应用程序时,我希望 TabControl 的 Width
到 increase/decrease 显示所有没有水平滚动条的 TabPages 并相应地调整表单的大小 Width
,以确保TabControl 和 ListView 可见。
下面是截图。
从该表格开始,我将在 运行 时添加 8 个标签,计算标签中文本的宽度 + 填充大小 x2(标签的两侧),然后调整大小根据需要进行控制。
public Form1()
{
InitializeComponent();
//Clear our default tabs.
tabControl1.TabPages.Clear();
//Add more tabs than would be visible by default
for (int i=1;i<=8;i++)
{
tabControl1.TabPages.Add("Tab " + i.ToString());
}
ResizeTabControl();
ResizeListViewControl();
ResizeForm();
}
void ResizeTabControl()
{
int tabCount = tabControl1.TabCount;
float length = 0;
using (Graphics g = CreateGraphics())
{
//Iterate through the tabs and get the length of the text.
for (int i = 0; i <= tabCount - 1; i++)
length += g.MeasureString(tabControl1.TabPages[i].Text, tabControl1.Font).Width;
}
//Resize the tab control where X is the length of all text in the tabs plus padding x 2 x total tabs.
tabControl1.Size = new Size(Convert.ToInt32(length) + (tabCount * 2 * tabControl1.Padding.X), tabControl1.Width);
}
void ResizeListViewControl()
{
//Move listview 10 pixels away from tabcontrol's edge
listView1.Location = new Point(tabControl1.Location.X + tabControl1.Width + 10, listView1.Location.Y);
}
void ResizeForm()
{
//Resize form to accomodate changes.
this.Width = listView1.Location.X + listView1.Width + 20;
}
说完一切后,这就是它的样子:
还有 20 个标签,因为为什么不呢。
要auto-size一个TabControl到它的Headers的大小,你需要计算每个Header的文本宽度。如果 TabControl.SizeMode is set to Fixed, since you can set the ItemSize.Width 和所有 Header 具有相同的宽度,则更简单。
如果TabControl.SizeMode
设置为默认Normal
,则必须测量每个Header的Text,为边框添加1px
(2px
如果它是第二个 TabPage - 基本控件中的小 bug)。
第一种情况,TabControl的大小为:
tabControl1.Width = tabControl1.TabPages.Count * (tabControl1.ItemSize.Width + 1);
在第二种情况下,使用TextRendrer.MeasureText测量每个Header的文本:
private int MeasureTabPagesWidth(TabControl tc)
{
if (tc.TabPages.Count == 0) return tc.Width;
int newWidth = 0;
int border = tc.TabPages.Count == 2 ? 2 : 1;
var flags = TextFormatFlags.LeftAndRightPadding;
using (var g = tc.CreateGraphics()) {
foreach (TabPage tab in tc.TabPages) {
newWidth += TextRenderer.MeasureText(g, tab.Text, tc.Font,
new Size(int.MaxValue, tc.Font.Height + 4), flags).Width + border;
}
}
return newWidth;
}
设置布局:
- 向您的表单添加一个 TableLayoutPanel,具有一行和两列(即,删除一行)
- 将 TabControl 添加到左侧的 Cell,将 ListBox 添加到另一个 Cell。
- 将两个单元格的样式设置为
AutoSize
(在 添加控件后)。 - 将 TableLayoutPanel 设置为:
AutoSize = true
、AutoSizeMode
= GrowAndShrink
- 同样的方法将Form设置为auto-size
- 将表格的 MinimumSize and MaximumSize. The former is usually set to the design size, the latter is up to you; you could use the current Screen WorkingArea 设置为参考。
- 在创建或加载窗体时(即在其构造函数或
OnLoad()
或Form.Load
中)计算TabControl的新宽度,因此窗体将auto-size到TableLayoutPanel 的大小,依次 auto-size 到其 child 控件的大小。
现在您可以在 run-time 添加或删除 TabPages 并且表单将 auto-size 到您在 TabControl.ControlAdded and TabControl.ControlRemoved 事件处理程序中计算的宽度(同时检查添加的控件是否是输入 TabPage
).
例子:
MeasureTabPagesWidth()
方法就是上面的那个- TableLayoutPanel 名为
tlp1
- TabControl 名为
tabControl1
- 视觉示例中使用的按钮具有定义其作用的名称。
public partial class AutoSizeForm : Form
{
public AutoSizeForm()
{
InitializeComponent();
tabControl1.Width = MeasureTabPagesWidth(tabControl1);
}
private void tabControl1_ControlAdded(object sender, ControlEventArgs e)
{
// Event notified after the TabPage has been added
if (e.Control is TabPage) {
tabControl1.Width = MeasureTabPagesWidth(tabControl1);
}
}
private void tabControl1_ControlRemoved(object sender, ControlEventArgs e)
{
if (e.Control is TabPage) {
// Use deferred execution, since the TabPage is removed after
// the event handler method completes.
BeginInvoke(new Action(()=> tabControl1.Width = MeasureTabPagesWidth(tabControl1)));
}
}
private void btnAddPage_Click(object sender, EventArgs e)
{
tabControl1.TabPages.Add(new TabPage("New TabpPage Text"));
}
private void btnRemovePage_Click(object sender, EventArgs e)
{
if (tabControl1.TabPages.Count > 0) {
tabControl1.TabPages.RemoveAt(tabControl1.TabPages.Count - 1);
}
}
private void btnAddCtlToTLP_Click(object sender, EventArgs e)
{
tlp1.ColumnCount += 1;
tlp1.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
var mc = new MonthCalendar();
tlp1.SetColumn(mc, tlp1.ColumnCount - 1);
tlp1.Controls.Add(mc);
}
}
它是这样工作的:
在 Windows 7 中测试,因为这似乎是正在使用的系统
示例项目:
Sample Project on Google Drive (.Net Framework 4.8
- C# 7.3
)
在 运行