最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - Display of buttons according to the number of objects - Stack Overflow

programmeradmin3浏览0评论

I'm working on a pig management application in C# WinForms with .NET 9. My approach is basic, not professional.

Each pen can hold up to 4 pigs of the same gender and is represented by a Panel. I have successfully assigned pigs to their respective pens, but I have an issue displaying them on the screen: the buttons representing the pigs appear in a list format, one below the other, and overlap due to their size. I would like them to be arranged in a grid inside each Panel.

Here is the method I use to dynamically add the buttons:

private void DisplayPigsInPanels()
{
    // Clear the panels before adding new buttons
    panel1.Controls.Clear();
    panel2.Controls.Clear();
    panel3.Controls.Clear();
    panel4.Controls.Clear();

    // List of panels, each representing a pen
    List<Panel> panels = new List<Panel> { panel1, panel2, panel3, panel4 };

    for (int i = 0; i < cages.Count; i++)
    {
        Panel currentPanel = panels[i];
        int posY = 10;

        foreach (Pig p in cages[i].Pigs)
        {
            Button btnPig = new Button();
            btnPig.Image = p.image;
            btnPig.Size = new Size(150, 150);
            btnPig.Location = new Point(10, posY);
            btnPig.Tag = p;

            // Assign click event
            btnPig.Click += Pig_Click;

            currentPanel.Controls.Add(btnPig);
            posY += 40; // This makes the buttons stack in a column
        }
    }
}

Problem The buttons are displayed in a list format, one below the other. Since each pen can have up to 4 pigs, I would like them to be arranged in a 2x2 grid inside each Panel, instead of stacking in a single column.

Question How can I arrange the buttons in a grid layout inside the Panel? Is there a better control than Panel to achieve this more easily?

Any suggestions would be helpful. Thanks!

image of the current result image

Note: The program information is stored in a document which, upon starting, is given the path. There is not always the same number of piglets and cages of each sex.

I'm working on a pig management application in C# WinForms with .NET 9. My approach is basic, not professional.

Each pen can hold up to 4 pigs of the same gender and is represented by a Panel. I have successfully assigned pigs to their respective pens, but I have an issue displaying them on the screen: the buttons representing the pigs appear in a list format, one below the other, and overlap due to their size. I would like them to be arranged in a grid inside each Panel.

Here is the method I use to dynamically add the buttons:

private void DisplayPigsInPanels()
{
    // Clear the panels before adding new buttons
    panel1.Controls.Clear();
    panel2.Controls.Clear();
    panel3.Controls.Clear();
    panel4.Controls.Clear();

    // List of panels, each representing a pen
    List<Panel> panels = new List<Panel> { panel1, panel2, panel3, panel4 };

    for (int i = 0; i < cages.Count; i++)
    {
        Panel currentPanel = panels[i];
        int posY = 10;

        foreach (Pig p in cages[i].Pigs)
        {
            Button btnPig = new Button();
            btnPig.Image = p.image;
            btnPig.Size = new Size(150, 150);
            btnPig.Location = new Point(10, posY);
            btnPig.Tag = p;

            // Assign click event
            btnPig.Click += Pig_Click;

            currentPanel.Controls.Add(btnPig);
            posY += 40; // This makes the buttons stack in a column
        }
    }
}

Problem The buttons are displayed in a list format, one below the other. Since each pen can have up to 4 pigs, I would like them to be arranged in a 2x2 grid inside each Panel, instead of stacking in a single column.

Question How can I arrange the buttons in a grid layout inside the Panel? Is there a better control than Panel to achieve this more easily?

Any suggestions would be helpful. Thanks!

image of the current result image

Note: The program information is stored in a document which, upon starting, is given the path. There is not always the same number of piglets and cages of each sex.

Share Improve this question edited Mar 18 at 0:41 gunr2171 17.6k26 gold badges66 silver badges100 bronze badges asked Mar 18 at 0:38 chamorrochamorro 175 bronze badges 3
  • 3 TableLayoutPanel ? – ProgrammingLlama Commented Mar 18 at 0:44
  • It seems the code you've posted is a mostly-correctly attempt at getting the buttons to stack. Have you tried writing the code to make them in a grid? You're "determining" the Y position (although it's incorrect), but leaving the X always the same value. – gunr2171 Commented Mar 18 at 0:44
  • Hey you can drag a table layout control to your form and set the rows and column counts to match a grid you would like to see and set it to resize like the parent. – user23633404 Commented Mar 18 at 4:25
Add a comment  | 

2 Answers 2

Reset to default 1

I'd like to suggest using FlowLayoutPanel controls for this, where you could add and remove pens and pigs either on the UI or programmatically. The advantage is that the pigs and pens arrange themselves.


The basic idea is to have a UserControl to represent a Pig.

public partial class Pig : UserControl
{
    public Pig()
    {
        InitializeComponent();
        buttonRemove.Click += (sender, e) => Parent?.Controls.Remove(this); ;
    }
}

Another UserControl would represent a Pen and contain a FlowLayoutPanel that accepts up to four pig controls.

public partial class Pen : UserControl
{
    public Pen()
    {
        InitializeComponent();
        buttonAdd.Click += (sender, e) =>
        {
            flowLayoutPanel.Controls.Add(new Pig
            {
                Height = 
                    flowLayoutPanel.Height - 
                    flowLayoutPanel.Padding.Vertical - this.Margin.Vertical,
            });
            AutoResize();
            buttonAdd.Enabled = flowLayoutPanel.Controls.Count < 4;
        };
        buttonRemove.Click += (sender, e) => Parent?.Controls.Remove(this);
        SizeChanged += (sender, e) => AutoResize();
    }

    private void AutoResize()
    {
        foreach (var pig in flowLayoutPanel.Controls.OfType<Pig>())
        {
            var availableWidth = 
                flowLayoutPanel.Width - 
                SystemInformation.VerticalScrollBarWidth;
            pig.Width =
                (flowLayoutPanel.Width/4) - 
                pig.Margin.Horizontal - flowLayoutPanel.Padding.Horizontal;
        }
    }
}

MainForm with FlowLayoutPanel

The code snippet below shows how to add pens and pigs with the UI. You can easily do programmatic versions of this basic scheme as well. Tips:

  • Make sure that AutoScroll is enabled
  • Constrain the max width of the main FlowLayoutPanel
  • Leave room for the scrollbar (even when it isn't visible.
public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        buttonAdd.Click += (sender, e) =>
        {
            flowLayoutPanelPens.Controls.Add(new Pen 
            {
                Width =
                    (flowLayoutPanelPens.Width - flowLayoutPanelPens.Padding.Horizontal) 
                    - SystemInformation.VerticalScrollBarWidth,
            });
            flowLayoutPanelPens.MaximumSize = 
                new Size(Width - SystemInformation.VerticalScrollBarWidth, 0);
        };
        Load += (sender, e) => FloatPlusButton();
    }

    private void FloatPlusButton()
    {
        var flowRect = flowLayoutPanelPens.Bounds;
        Controls.Add(buttonAdd);
        Controls.SetChildIndex(buttonAdd, 0);
        buttonAdd.Left = flowRect.Right - buttonAdd.Width;
        buttonAdd.Top = flowRect.Bottom - buttonAdd.Height;
    }
}

Create a custom control: a panel with four buttons properly arranged. Add appropriate member functions to set button information. Add these pigpen controls to a flow layout panel.

发布评论

评论列表(0)

  1. 暂无评论