【问题标题】:Why does the horizontal scrollbar still appear in this panel?为什么水平滚动条仍然出现在这个面板中?
【发布时间】:2015-10-16 01:32:44
【问题描述】:

我有一个 Panel,其中包含许多较小的面板。
包含面板将 AutoScroll 设置为 true,这样当小面板过多时,我可以向下滚动。
小面板的宽度始终设置为容器的客户端宽度(允许边框等),因此不应该显示水平滚动条。
除非最后一个子面板接触到包含面板的底部,否则这似乎大多是这种情况,然后水平滚动条会在我不想要的时候出现!

我试过changing the properties to disable it,但这似乎没有效果。
我试过always showing the vertical scrollbar(因为这是可以接受的),但它只是短暂地显示了一个非常丑陋的条,然后消失并被原生条取代。
我可以看到other people with the same problem,但没有解决方案。

将以下代码粘贴到新的 Winform 中,然后尝试以下步骤:

  1. 按“添加”按钮 4 次以获得 4 个面板,它们应该离开容器的底部。
  2. 垂直调整表单大小,以便在最后一个面板之后有一些空白。
  3. 现在小心地垂直调整表单的大小,使最后一个面板的底部接触到容器的底部。滚动条应该出现在这里,它可能需要一些“摆动”。

    static List<Panel> listOfPanels;
    static Panel panel;
    static bool flipflop;
    
    private void Form1_Load(object sender, EventArgs e)
    {
        Height = 400;
        Width = 400;
    
        listOfPanels = new List<Panel>();
    
        panel = new Panel()
        {
            Height = this.ClientSize.Height - 20,
            Width = 200,
            Top = 10,
            Left = 10,
            BackColor = Color.White,
            BorderStyle = BorderStyle.FixedSingle,
            Padding = Padding.Empty,
            Margin = Padding.Empty,
            Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom,
        };
    
        // I'VE TRIED DISABLING IT HERE!
        panel.AutoScroll = false;
        panel.HorizontalScroll.Enabled = false;
        panel.HorizontalScroll.Visible = false;
        panel.AutoScroll = true;
    
        panel.Resize += panel_Resize;
    
        Button button = new Button()
        {
            Text = @"Add",
            Size = new Size(100, 50),
            Top = 10,
            Left = 20 + panel.Width
        };
        button.Click += button_Click;
    
        Controls.Add(panel);
        Controls.Add(button);
    }
    
    void panel_Resize(object sender, EventArgs e)
    {
        renderSubPanels();
    }
    
    void button_Click(object sender, EventArgs e)
    {
        Panel subPanel = new Panel()
        {
            Height = 100,
            BackColor = flipflop ? Color.PeachPuff : Color.PowderBlue,
            Top = (listOfPanels.Count * 100) - Math.Abs(panel.AutoScrollPosition.Y)
        };
    
        listOfPanels.Add(subPanel);
    
        flipflop = !flipflop;
    
        panel.Controls.Add(subPanel);
    
        renderSubPanels();
    }
    
    void renderSubPanels()
    {
        panel.SuspendLayout();
        bool verticalScrollVisible = listOfPanels.Count * 100 > panel.ClientSize.Height;
        foreach (Panel p in listOfPanels)
        {
            if (verticalScrollVisible)
            {
                p.Width = panel.Width - System.Windows.Forms.SystemInformation.VerticalScrollBarWidth - 2;
            }
            else
            {
                p.Width = panel.Width - 2;
            }
    
            p.Top = (listOfPanels.IndexOf(p) * 100) - Math.Abs(this.AutoScrollPosition.Y);
        }
        panel.ResumeLayout();
    }
    

在我的实际程序中,它实际上是一个我正在使用的自定义面板,因此我对想法持开放态度。我只是想让讨厌的事情消失!
谢谢!

【问题讨论】:

  • 我仍然不明白你想要做什么。因此,如果您尝试调整主窗体的大小并且父面板的长度足以容纳所有子面板,那么父面板上的垂直滚动将被禁用,对吗?

标签: c# winforms


【解决方案1】:

注释掉自动滚动:

//panel.AutoScroll = true;

然后添加这段代码:

panel.ControlAdded += panel_ControlAdded;

void panel_ControlAdded(object sender, ControlEventArgs e) {
  panel.AutoScrollMinSize = new Size(0,
    panel.Controls.Cast<Control>().Sum(x => x.Height));
}

FlowLayoutPanel 可能会为您执行此操作。

您当前的代码做了太多不必要的工作。您不需要 renderSubPanels() 方法,因此您可以将其注释掉,并且当滚动位置不在起始位置时,您的 Top 位置定位不起作用。只需设置子面板的 Anchor 属性,它就会正确说明 VerticalScrollBar 是否可见:

Panel subPanel = new Panel() {
  Height = 100,
  BackColor = flipflop ? Color.PeachPuff : Color.PowderBlue,

  // updated properties:
  Top = panel.Controls.Cast<Control>().Sum(x => x.Height) + panel.AutoScrollPosition.Y,
  Width = panel.ClientSize.Width, 
  Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right
};

【讨论】:

  • 不幸的是,这似乎不起作用,我仍然得到水平滚动条。我会尝试使用 FlowLayoutPanel 作为最后的手段,但这意味着重写我宁愿避免的大部分控件。以上只是一个非常基本的问题示例,与真实情况相去甚远:-)
  • @Equalsk 我没有得到我推荐的更改的水平滚动条。请记住在面板控件上关闭 AutoScroll。你也可以忽略那些panel.HorizontalScroll 属性。
  • 您在进行更改之前确定得到它吗?它在几个像素的容差范围内。我肯定已经评论了 AutoScroll 属性的所有实例,就像你说的那样,所以不是那样的。我在 Windows 8 上,也许它是特定于操作系统的?
  • @Equalsk 我只处理您提供的代码。关闭 AutoScroll 并且 AutoScrollMinSize.Width = 0,您将永远看不到水平滚动条。这就是我的代码所做的。
  • 嗯,不知道还能告诉你什么。我也只使用这个例子。不用担心顶部不起作用,它在真实版本中会起作用,这只是为了本文的目的而进行的演示。感谢您的宝贵时间!
【解决方案2】:

我认为你可以通过使用panel.PerformLayout 而不是SuspendLayout/ResumeLayout 来获得你想要的行为:

    void renderSubPanels()
    {
        //panel.SuspendLayout();
        bool verticalScrollVisible = listOfPanels.Count * 100 > panel.ClientSize.Height;
        foreach (Panel p in listOfPanels)
        {
            if (verticalScrollVisible)
            {
                p.Width = panel.Width - System.Windows.Forms.SystemInformation.VerticalScrollBarWidth - 2;
            }
            else
            {
                p.Width = panel.Width - 2;
            }

            p.Top = (listOfPanels.IndexOf(p) * 100) - Math.Abs(this.AutoScrollPosition.Y);
        }
        //panel.ResumeLayout();
        panel.PerformLayout();
    }

这似乎对我有用。

【讨论】:

  • 我会在明天有能力的时候先试试这个,然后告诉你它是否有效。谢谢!
  • 这是最简单的答案,效果很好,谢谢。
猜你喜欢
  • 1970-01-01
  • 2012-11-19
  • 2015-10-27
  • 1970-01-01
  • 1970-01-01
  • 2011-03-28
  • 1970-01-01
  • 2014-10-01
  • 2012-03-14
相关资源
最近更新 更多