如何在WinForms中禁用表格面板的水平滚动条

18

你好,我有一个表格布局面板,我需要动态地将控件绑定到它上面。当项目数量超过面板的高度时,垂直滚动条显然会出现,这没有问题。

但与此同时,即使项目的宽度小于面板的宽度,水平滚动条也会出现。我该如何防止这种情况发生?


我知道这篇文章已经写了4年,但是今天我遇到了同样的问题(或者非常相似),解决方法就是简单地将AutoScroll = false。希望这能帮助到有需要的人! - Cullub
5
“AutoScroll = false”将同时禁用垂直滚动条,但问题是如何仅禁用水平滚动条。 - Nikita
10个回答

43
int vertScrollWidth = SystemInformation.VerticalScrollBarWidth;

tableLayoutPanel1.Padding = new Padding(0, 0, vertScrollWidth, 0);

2
有趣的解决方案。你是否碰巧知道这个魔法为什么有效? - Emperor Orionii
1
已在.NET 4.6.2上进行了测试。当高度不足时,它确实会移除水平滚动条,但问题是当垂直滚动条出现时,它会在右侧产生一个宽边距,而该边距不会消失。我希望TableLayoutPanel可以填充窗口宽度。 - Damn Vegetables
我们将这段代码放在哪里?是放在窗体类的构造函数中还是其他地方? - Ahmer Ali Ahsan

9
我有一个问题,我的TableLayoutPanel中包含了一些GroupBox,且只设置了单列宽度为100%。我不想手动设置它们的大小,希望它们能够随着窗体的调整而自适应大小。
奇怪的是,将TableLayoutPanel的Right Padding设置为1(不是滚动条的宽度 - 这会留下一个滚动条大小的间隙),就完全解决了这个问题。这是在C# 2010 Express、.NET 4、Windows 8中实现的,不知道这种曲线救国方法是否适用于其他版本。
将内边距设置为0似乎可以在IDE中解决问题,但实际运行时问题仍然存在。
对我来说,这似乎是TableLayoutPanel中的某种错误...或者可能只是我拥有的控件和属性的特定组合(这是一个相当复杂的布局)造成的。

1
已确认支持.NET 3.5和Windows 7。 - miasbeck
已确认适用于.NET 4.6.2,Windows 10和Visual Studio 2017。但需要将Padding设置为右侧9像素。仅将1像素设置可能只能在编辑器中解决问题。 - Manuel Hoffmann
已确认支持.NET 3.5、Windows 7和SharpDevelop 4.4。但是我不得不将其调整到6像素才能使其正常工作。 - Couitchy
谢谢,填充1适用于.NET 4.5.1,Windows 10,VS 2017。有趣。 - Quirzo
1
必须添加第二个注释:今天我遇到了类似的情况,其中1像素的填充不起作用。但是2像素可以。因此,请尝试不同的值。 - Quirzo
已确认支持.NET 4.7.2、Visual Studio 2019和Windows 10。需要将Padding.Right设置为2px。 - d.k.

7

今天在解决这个问题时,我花费了一些时间,但最终得出了以下结果:

  1. Create a new class that inherits from TableLayoutPanel (lets call it MyTableLayoutPanel), and override the MaximumSize property like this:

    public override Size MaximumSize
    {
        get
        {
            if (Parent != null)
                return new Size(Parent.Width, 0);
            else
                return base.MaximumSize;
        }
        set
        {
            base.MaximumSize = value;
        }
    }
    

    You could of course make it more general purpose by adding another property that decides whether or not you should return the altered MaximumSize or not, but hopefully that much is obvious to anyone that's reading this.

  2. Change the TableLayoutPanel that you've got to the new MyTableLayoutPanel type.

  3. Add it to a regular Panel. Enable AutoScroll on this Panel instead of the MyTableLayoutPanel (disable it there if you haven't already).

  4. Set the MyTableLayoutPanel AutoSize property to true and its Anchor property to Left, Right and Top.


这是唯一一个真正解决了我的布局问题的方案,谢谢! - inexcitus

3

我知道这个问题已经存在很长时间了。但可能其他人也可以从我的解决方案中受益。

诀窍在于,如果自动滚动属性为true,则禁用水平滚动条不起作用。因此,只需禁用自动滚动,禁用水平滚动条,然后再将自动滚动切换为true即可。这对我有效。

只需将以下代码添加到某个位置,例如构造函数或窗体加载事件。

tableLayoutPanel1.AutoScroll = false;
tableLayoutPanel1.HorizontalScroll.Enabled = false;
tableLayoutPanel1.AutoScroll = true;

有解决方案和技巧。技巧是经验的标志,应该受到赞赏。这解决了我的问题。 - Ad Kahn

1

我曾经遇到过这个问题。

很多人在Datagrid中也遇到了同样的问题。但是,对于这个问题没有确切的解决方案,你将不得不根据使用手动决定面板的尺寸。

tableLayoutPanel1.HorizontalScroll.Enabled = false;

这样做将禁用水平滚动条,但您必须手动调整表布局面板的尺寸。

另一种方法可能是在运行时计算tablelayoutpanel的可能宽度,如果大于您设置的值,则可以启用它。

tableLayoutPanel1.HorizontalScroll.Enabled = true;

2
不起作用。水平滚动条仍然像以前一样出现。替代的“Visible”属性也不起作用。 - ygoe

1
这在.NET 3.5中完美运行,而其他解决方案并没有给我 完全 想要的结果:
  if (this.TableLayoutPanel1.HorizontalScroll.Visible)
  {
    int newWid = this.TableLayoutPanel1.Width -
                  (2 * SystemInformation.VerticalScrollBarWidth);
    //this.TableLayoutPanel1.Padding = new Padding(0, 0, newWid, 0);
    foreach (Control ctl in this.TableLayoutPanel1.Controls)
    {
      ctl.Width = newWid;
    }
  }

1

你的问题是你的项目恰好与布局面板的宽度相同,因此当垂直滚动条出现时,它会稍微切入你的控件,强制水平滚动吗?如果是这样,你可以通过减小控件的宽度来考虑滚动条的可能性,或者在滚动条出现时尝试调整它们。


1
我通过使用简单的面板来解决了这个问题,将表格布局面板固定在其中。然后我使滚动条不是 TLP 的,而是面板的。对我来说,这很好用。
我认为 TLP 的不同列和行存在计算每个宽度的问题,因此即使不必要,也会显示垂直滚动条。

1
我通过使用反射找到了这个问题的完美解决方案。 您可以尝试以下代码:
static MethodInfo funcSetVisibleScrollbars;
static EventHandler ehResized;

public static void DisableHorizontalScrollBar(this ScrollableControl ctrl)
{
     //cache the method info
     if(funcSetVisibleScrollbars == null)
     {
           funcSetVisibleScrollbars = typeof(ScrollableControl).GetMethod("SetVisibleScrollbars",
                BindingFlags.Instance | BindingFlags.NonPublic);
     }

     //init the resize event handler
     if(ehResized == null)
     {
           ehResized = (s, e) =>
           {
                funcSetVisibleScrollbars.Invoke(s, new object[] { false, (s as ScrollableControl).VerticalScroll.Visible });
           };
     }

     ctrl.Resize -= ehResized;
     ctrl.Resize += ehResized;
}

0

这些解决方案并非在所有情况下都有效;我最终需要将它们结合使用:

public void hideHorizontalScrollBar(ref TableLayoutPanel pan)
{
    if (!pan.HorizontalScroll.Visible)
        return;
    pan.Padding = new Padding(0, 0, 0, 0);
    while (!!pan.HorizontalScroll.Visible || pan.Padding.Right >= SystemInformation.VerticalScrollBarWidth * 2)
    pan.Padding = new Padding(0, 0, pan.Padding.Right + 1, 0);
}

重要提示:此函数可以在窗体加载时调用一次,但也必须在布局调整事件中调用。


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