FlowLayoutPanel - автоматическая ширина для элементов управления? - PullRequest
39 голосов
/ 22 марта 2011

возможно ли сделать вставленные элементы в FlowLayoutPanel автоматически размером с FlowLayoutPanel? Вот пример:

Форма с 1 FlowLayoutPanel и 3 кнопками внутри:

enter image description here

если я изменяю размер формы, элементы управления выглядят так: они располагаются «слева направо»

enter image description here

То, что я хочу, это: элементы управления должны иметь ширину FlowLayoutPanel:

enter image description here

Есть идеи, как это сделать? Я изменил FlowDirection и поиграл со свойством Anchor, но безуспешно.

Конечно, я могу изменить размеры элементов управления в событии FlowLayoutPanel_Resize, но я хочу добавить около 500 пользовательских элементов управления - я проверил это, и это медленно.

Ответы [ 7 ]

37 голосов
/ 22 марта 2011

Я предлагаю вам использовать TableLayoutPanel с одним столбцом в этом случае.Я нашел TableLayoutPanel гораздо более предсказуемым и надежным, чем FlowLayoutPanel.

Другой вариант, если вы все еще хотите использовать FlowLayoutPanel, это установить ширину первого элемента управления на желаемую и использовать Dock = Top для всех остальных элементов управления.

19 голосов
/ 20 марта 2013

Это простой способ сделать это.Просто свяжите свой размер SizeChanged с flowLayoutPannel и измените размер содержащего его элемента управления.Нравится:

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();
}
6 голосов
/ 12 апреля 2017

вот мой класс 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;
                }
            }
        }
    }
}
3 голосов
/ 29 сентября 2015

FlowLayoutPanel упорядочивает элементы управления определенным образом, в соответствии с MSDN :

... для вертикальных направлений потока, элемент управления FlowLayoutPanel вычисляет ширину подразумеваемойстолбец от самого широкого дочернего элемента управления в столбце .Все остальные элементы управления в этом столбце со свойствами Anchor или Dock выравниваются или растягиваются, чтобы соответствовать этому подразумеваемому столбцу.Поведение работает аналогичным образом для горизонтальных направлений потока.

Это не идеально, но вы можете сделать это изначально, если один дочерний элемент управления имеет ту же ширину, что и контейнер, иостальные элементы управления установлены на Dock.

2 голосов
/ 23 февраля 2012

Предлагаю ... попробуйте поиграть с якорями кнопок ... попробуйте установить его как

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

или установите его в свойствах ...

и затем поместите его внутри панели вместо FlowLayoutPanel ...;)

1 голос
/ 13 августа 2018

Здесь нет необходимости в FlowLayoutPanel.

Вы сможете делать то, что хотите, с помощью обычного Panel элемента управления.Прикрепите его со всех четырех сторон, чтобы он растягивался вместе с вашей формой, затем добавьте кнопки и установите их все в Dock: Top.

Работа выполнена.

0 голосов
/ 05 декабря 2018

Как уже говорилось в других ответах, самой панели достаточно для управления вашими кнопками.Немного кода, который работает для меня:

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

Хорошего дня.

...