FlowLayoutPanel - 控件的自动宽度?

发布于 2024-10-24 14:10:42 字数 543 浏览 1 评论 0原文

是否可以使 FlowLayoutPanel 中插入的项目自动调整 FlowLayoutPanel 的大小?这是一个示例:

一个包含 1 个 FlowLayoutPanel 和 3 个按钮的表单:

在此处输入图像描述

如果我调整表单大小,控件看起来像这样:它们“从左到右”排列

在此处输入图像描述

我想要的是这样的:控件应该具有FlowLayoutPanel 的宽度:

在此处输入图像描述

有任何想法如何做到这一点吗?我更改了 FlowDirection 并使用了 Anchor 属性,但没有成功。

我当然可以在 FlowLayoutPanel_Resize 事件中调整控件的大小,但我想添加大约 500 个用户控件 - 我测试了它,它很慢。

is it possible to make the inserted items in FlowLayoutPanel automatic size of the FlowLayoutPanel? Here is an example:

A form with 1 FlowLayoutPanel and 3 buttons inside:

enter image description here

if I resize the form, the controls look like this: they arrange "left to right"

enter image description here

What I want is this: The controls should have the width of the FlowLayoutPanel:

enter image description here

Any Ideas how to do this? I changed the FlowDirection and played with the Anchor property but with no luck.

I could of course Resize the controls in the FlowLayoutPanel_Resize event, but I want to add about 500 usercontrols - I tested it and it is slow.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

半葬歌 2024-10-31 14:10:42

在这种情况下,我建议您使用带有一列的 TableLayoutPanel。我发现 TableLayoutPanel 比 FlowLayoutPanel 更可预测、更可靠。

如果您仍想使用 FlowLayoutPanel,另一种选择是将第一个控件的宽度设置为所需的宽度,并对所有其他控件使用 Dock = Top。

I suggest you using TableLayoutPanel with one column in this case. I have found TableLayoutPanel much more predictable and solid than FlowLayoutPanel.

Another option, if you still want to use FlowLayoutPanel, is to set first control width to desired one, and use Dock = Top for all other controls.

青春如此纠结 2024-10-31 14:10:42

这是一个简单的方法来做到这一点。
只需绑定 flowLayoutPannel 的 SizeChanged 事件并调整包含控件的大小即可。
喜欢:

private void myFlowLayoutPannel_SizeChanged(object sender, EventArgs e)
{
    myFlowLayoutPannel.SuspendLayout();
    foreach (Control ctrl in pnSMS.Controls)
    {
        if (ctrl is Button) ctrl.Width = pnSMS.ClientSize.Width;
    }
    myFlowLayoutPannel.ResumeLayout();
}

It's simple way to do this.
Just bind the SizeChanged evnent of you flowLayoutPannel and resize the containing control.
Like:

private void myFlowLayoutPannel_SizeChanged(object sender, EventArgs e)
{
    myFlowLayoutPannel.SuspendLayout();
    foreach (Control ctrl in pnSMS.Controls)
    {
        if (ctrl is Button) ctrl.Width = pnSMS.ClientSize.Width;
    }
    myFlowLayoutPannel.ResumeLayout();
}
风为裳 2024-10-31 14:10:42

这里我有我的 StackPanel 类:

/// <summary>
/// A stackpanel similar to the Wpf stackpanel.
/// </summary>
public class StackPanel: FlowLayoutPanel
{
    public StackPanel(): base()
    {
        InitializeComponent();
        this.ForceAutoresizeOfControls = true;
    }

    private void InitializeComponent()
    {
        this.SuspendLayout();
        //
        // StackPanel
        //
        this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
        this.WrapContents = false;
        this.ResumeLayout(false);
    }

    /// <summary>
    /// Override it just in order to hide it in design mode.
    /// </summary>
    [Browsable(false)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public new bool WrapContents
    {
        get { return base.WrapContents; }
        set { base.WrapContents = value; }
    }

    /// <summary>
    /// Override it just in order to set its default value.
    /// </summary>
    [DefaultValue(typeof(AutoSizeMode), "GrowAndShrink")]
    public override AutoSizeMode AutoSizeMode
    {
        get { return base.AutoSizeMode; }
        set { base.AutoSizeMode = value; }
    }

    /// <summary>
    /// Get or set a value that when is true forces the resizing of each control.
    /// If this value is false then only control that have AutoSize == true will be resized to
    /// fit the client size of this container.
    /// </summary>
    [DefaultValue(true)]
    public bool ForceAutoresizeOfControls { get; set; }

    protected override void OnSizeChanged(EventArgs e)
    {
        base.OnSizeChanged(e);
        this.SuspendLayout();
        switch (FlowDirection)
        {
            case FlowDirection.BottomUp:
            case FlowDirection.TopDown:
                foreach (Control control in this.Controls)
                    if (ForceAutoresizeOfControls || control.AutoSize)
                        control.Width = this.ClientSize.Width - control.Margin.Left - control.Margin.Right;
                break;
            case FlowDirection.LeftToRight:
            case FlowDirection.RightToLeft:
                foreach (Control control in this.Controls)
                    if (ForceAutoresizeOfControls || control.AutoSize)
                        control.Height = this.ClientSize.Height - control.Margin.Top - control.Margin.Bottom;
                break;
            default:
                break;
        }
        this.ResumeLayout();
    }

    protected override void OnLayout(LayoutEventArgs levent)
    {
        base.OnLayout(levent);

        if (levent != null && levent.AffectedControl != null)
        {
            Control control = levent.AffectedControl;
            if (ForceAutoresizeOfControls || control.AutoSize)
            {
                switch (FlowDirection)
                {
                    case FlowDirection.BottomUp:
                    case FlowDirection.TopDown:
                        control.Width = this.ClientSize.Width - control.Margin.Left - control.Margin.Right;
                        break;
                    case FlowDirection.LeftToRight:
                    case FlowDirection.RightToLeft:
                        control.Height = this.ClientSize.Height - control.Margin.Top - control.Margin.Bottom;
                        break;
                    default:
                        break;
                }
            }
        }
    }
}

here I have my StackPanel class:

/// <summary>
/// A stackpanel similar to the Wpf stackpanel.
/// </summary>
public class StackPanel: FlowLayoutPanel
{
    public StackPanel(): base()
    {
        InitializeComponent();
        this.ForceAutoresizeOfControls = true;
    }

    private void InitializeComponent()
    {
        this.SuspendLayout();
        //
        // StackPanel
        //
        this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
        this.WrapContents = false;
        this.ResumeLayout(false);
    }

    /// <summary>
    /// Override it just in order to hide it in design mode.
    /// </summary>
    [Browsable(false)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public new bool WrapContents
    {
        get { return base.WrapContents; }
        set { base.WrapContents = value; }
    }

    /// <summary>
    /// Override it just in order to set its default value.
    /// </summary>
    [DefaultValue(typeof(AutoSizeMode), "GrowAndShrink")]
    public override AutoSizeMode AutoSizeMode
    {
        get { return base.AutoSizeMode; }
        set { base.AutoSizeMode = value; }
    }

    /// <summary>
    /// Get or set a value that when is true forces the resizing of each control.
    /// If this value is false then only control that have AutoSize == true will be resized to
    /// fit the client size of this container.
    /// </summary>
    [DefaultValue(true)]
    public bool ForceAutoresizeOfControls { get; set; }

    protected override void OnSizeChanged(EventArgs e)
    {
        base.OnSizeChanged(e);
        this.SuspendLayout();
        switch (FlowDirection)
        {
            case FlowDirection.BottomUp:
            case FlowDirection.TopDown:
                foreach (Control control in this.Controls)
                    if (ForceAutoresizeOfControls || control.AutoSize)
                        control.Width = this.ClientSize.Width - control.Margin.Left - control.Margin.Right;
                break;
            case FlowDirection.LeftToRight:
            case FlowDirection.RightToLeft:
                foreach (Control control in this.Controls)
                    if (ForceAutoresizeOfControls || control.AutoSize)
                        control.Height = this.ClientSize.Height - control.Margin.Top - control.Margin.Bottom;
                break;
            default:
                break;
        }
        this.ResumeLayout();
    }

    protected override void OnLayout(LayoutEventArgs levent)
    {
        base.OnLayout(levent);

        if (levent != null && levent.AffectedControl != null)
        {
            Control control = levent.AffectedControl;
            if (ForceAutoresizeOfControls || control.AutoSize)
            {
                switch (FlowDirection)
                {
                    case FlowDirection.BottomUp:
                    case FlowDirection.TopDown:
                        control.Width = this.ClientSize.Width - control.Margin.Left - control.Margin.Right;
                        break;
                    case FlowDirection.LeftToRight:
                    case FlowDirection.RightToLeft:
                        control.Height = this.ClientSize.Height - control.Margin.Top - control.Margin.Bottom;
                        break;
                    default:
                        break;
                }
            }
        }
    }
}
迟到的我 2024-10-31 14:10:42

这里不需要 FlowLayoutPanel

您应该能够使用普通的 Panel 控件执行您想要的操作。
将其固定在所有四个边,以便它随着您的形状延伸,然后添加按钮并将它们全部设置为“Dock: Top”。

编辑-回应@UsamaAziz 评论。

为了确保隐藏在面板底部之外的控件可以访问,请将面板的“AutoScroll”属性设置为 True。这将在需要时向面板添加垂直滚动条。

工作完成。

There is no need for a FlowLayoutPanel here.

You should be able to do what you want with a normal Panel control.
Anchor it at all four sides so that it stretches with your form, then add your buttons and set them all to Dock: Top.

EDIT - In response to @UsamaAziz comment.

To ensure the controls which are hidden beyond the bottom of the panel are accessible, set the "AutoScroll" property of the panel to True. This will add a vertical scrollbar to the panel when it is required.

Job Done.

心如狂蝶 2024-10-31 14:10:42

FlowLayoutPanel 根据 MSDN

...对于垂直流动方向,FlowLayoutPanel 控件计算
隐含列的宽度来自最宽的子控件
列。此列中带有 AnchorDock 的所有其他控件
属性被对齐或拉伸以适合这个隐含的列。这
水平流动方向的行为方式类似。


这并不理想,但您可以本机执行此操作,只要将一个子控件设置为与容器相同的宽度,并将其余控件设置为 Dock 即可。

The FlowLayoutPanel arranges controls in a particular way, according to MSDN:

...for vertical flow directions, the FlowLayoutPanel control calculates
the width of an implied column from the widest child control in the
column
. All other controls in this column with Anchor or Dock
properties are aligned or stretched to fit this implied column. The
behavior works in a similar way for horizontal flow directions.

Its not ideal, but you can do this natively, as long as one child control is set to the same width as the container, and the rest of the controls are set to Dock.

夏尔 2024-10-31 14:10:42

我建议...尝试使用按钮的锚点...尝试将其设置为

Button1.Anchor = (AnchoreStyle.Left or AnchoreStyle.Right)


在属性中设置它...

然后将其放入Panel而不是FlowLayoutPanel...;)

I Suggest... try playing with the anchors of the buttons... try setting it as

Button1.Anchor = (AnchoreStyle.Left or AnchoreStyle.Right)

or
set it in the properties...

and then put it inside a Panel instead of the FlowLayoutPanel... ;)

明天过后 2024-10-31 14:10:42

正如其他答案所述,面板本身足以处理您的按钮。一些对我有用的代码:

public class ButtonWindow : Panel
{
    public ButtonWindow()
    {
        Dock = DockStyle.Fill;
        AutoScroll = true;

        for (int i = 0; i < 500; i++) 
        {
           Button button = new Button() { Height = 100, Dock = DockStyle.Top };
           Controls.Add(button);
        }
    }
}

祝你有美好的一天。

As other answers stated, the Panel itself is sufficient to handle your buttons. Bit of code that works for me:

public class ButtonWindow : Panel
{
    public ButtonWindow()
    {
        Dock = DockStyle.Fill;
        AutoScroll = true;

        for (int i = 0; i < 500; i++) 
        {
           Button button = new Button() { Height = 100, Dock = DockStyle.Top };
           Controls.Add(button);
        }
    }
}

Have a nice day.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文