为什么水平滚动条仍会出现在此面板中?

时间:2015-10-15 16:19:16

标签: c# winforms

我有一个包含许多小面板的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();
    }
    
  4. 在我的真实程序中,它实际上是一个我正在使用的自定义面板,因此我对创意持开放态度。我只想让讨厌的东西消失!
    谢谢!

2 个答案:

答案 0 :(得分:2)

注释掉AutoScroll:

//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
};

答案 1 :(得分:1)

我认为您可以使用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();
    }

这似乎对我有用。