Problems passing on size change to child controls

1.1k views Asked by At

I am developing a WinForms app with a layered interface like this:

My UI Layout

Ignore Panel A. Next to that I have a TabControl with 2 tabs. On the TabPage of the 2nd tab, I have a few controls at the top for filtering data, and below that I have Panel B, a FlowLayoutPanel which displays a list of records from a database. Each record is displayed in a Panel C, which contains a variety of text fields, depending on the contents of the record.

The UI looks pretty good when it loads (but see problem #2, below). The first issue that I'm struggling with is properly handling a resize event for the main window. When the user drags the side of the main window to make it wider, the main form resizes the TabPage and Panel B, then it calls a method on Panel B to resize its contents. The controls at the top of the TabPage automatically spread out evenly across the top, in accordance with their settings. So far so good.

Panel B goes through its list of C Panels, adjusting the width of each. (Later I will add code for C Panel to adjust the widths of each text field accordingly.)

But at the moment, I'm stuck on 2 possibly related problems:

  1. I can't seem to get the C Panels to change their width. I had initially hoped that with the right settings of AutoSize, AutoScroll, etc. I could get what I want, but when that didn't work, I decided to add a resize event handler to take more control. That's not currently working right.

  2. Even prior to the resize, I set the width of Panel B to fit within the TabPage, and I set the FlowDirection of Panel B to FlowDirection.TopDown, yet once there are enough C Panels to exceed the height of Panel B, Panel B becomes double-width, and there is a 2nd column of C Panels in it. What I really want is to add a vertical scroll bar to scroll through the "TopDown" list.

When I had set AutoScroll to true for Panel B, I didn't get a vertical scroll bar (which I expected for a TopDown panel); instead I got a horizontal scroll bar & the panel grew to the right! So I turned off AutoScroll.

Here's some relevant code:

    class MainForm : Form
{
    private int priorHeight;
    private int priorWidth;
    private System.Windows.Forms.TabPage MyTabPage;
    private SelectableListPanel PanelB = null;

    ...

    private void OnResize(object sender, EventArgs e)
    {
        this.SuspendLayout();

        int vDiff = this.Height - priorHeight;
        int hDiff = this.Width - priorWidth;

        MyTabPage.Height += vDiff;
        MyTabPage.Width += hDiff;

        PanelB.Height += vDiff;
        PanelB.Width += hDiff;

        // tell PanelB to resize its record panels
        PanelB.PropagateResize(hDiff);

        ResumeLayout(false);
        PerformLayout();

        priorHeight = this.Height;
        priorWidth = this.Width;
    }
}

class SelectableListPanel : FlowLayoutPanel
{
    protected List<Panel> panels = new List<Panel>();

    public SelectableListPanel(List<Panel> Panels) : base()
    {
        FlowDirection = FlowDirection.TopDown;
        AutoScroll = false;
        AutoSize = false;
        panels = Panels;
    }

    ...

    public void PropagateResize(int hDiff)
    {
        foreach (Panel genPanel in panels)
        {
            genPanel.Width += hDiff;
            // TODO:  genPanel.PropagateResize(hDiff)
        }
    }
}

Any thoughts / suggestions?

2

There are 2 answers

0
Todd Hoatson On

Wanted to post some code which allowed me to test the suggestions I was receiving in the comments. My demo program does this:

enter image description here

And here's the code for it:

    public Form1()
{
    Panel BluePanel;
    Panel OrangePanel;
    Panel GreenPanel;
    List<Panel> PurplePanels;

    InitializeComponent();
    SuspendLayout();

    // Field 1
    TextBox f1 = new TextBox();
    f1.Text = "Main Form";
    f1.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
    f1.Font = new Font("Microsoft Sans Serif", 14F, FontStyle.Regular,
       GraphicsUnit.Point, (byte) 0);
    f1.Location = new Point(12, 12);
    f1.Multiline = true;
    f1.Name = "Field1";
    f1.Size = new Size(460, 32);
    f1.TabIndex = 0;

    // BluePanel
    BluePanel = new Panel();
    BluePanel.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
    BluePanel.BackColor = Color.Blue;
    BluePanel.Location = new Point(12, 50);
    BluePanel.Name = "BluePanel";
    BluePanel.Size = new Size(460, 402);
    BluePanel.TabIndex = 1;

    // Field 2
    TextBox f2 = new TextBox();
    f2.Text = "Blue Panel";
    f2.Anchor = f1.Anchor;
    f2.Font = f1.Font;
    f2.Location = f1.Location;
    f2.Name = "Field2";
    f2.Size = new Size(BluePanel.Width - 24, f1.Height);
    f2.TabIndex = 0;
    BluePanel.Controls.Add(f2);

    // OrangePanel
    OrangePanel = new Panel();
    OrangePanel.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
    OrangePanel.BackColor = Color.Orange;
    OrangePanel.Location = new Point(f2.Left, f2.Bottom + 6);
    OrangePanel.Name = "OrangePanel";
    OrangePanel.Size = new Size(BluePanel.Width - 24, BluePanel.Height - (f2.Bottom + 6 + 12));
    OrangePanel.TabIndex = 1;
    BluePanel.Controls.Add(OrangePanel);

    // Field 3
    TextBox f3 = new TextBox();
    f3.Text = "Orange Panel";
    f3.Anchor = f1.Anchor;
    f3.Font = f1.Font;
    f3.Location = f1.Location;
    f3.Name = "Field3";
    f3.Size = new Size(OrangePanel.Width - 24, f1.Height);
    f3.TabIndex = 0;
    OrangePanel.Controls.Add(f3);

    // GreenPanel
//    GreenPanel = new FlowLayoutPanel();
//    GreenPanel.FlowDirection = FlowDirection.LeftToRight;
    GreenPanel = new Panel();
    GreenPanel.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
    GreenPanel.AutoScroll = true;
    GreenPanel.AutoSize = false;
    GreenPanel.BackColor = Color.Green;
    GreenPanel.Location = new Point(f3.Left, f3.Bottom + 6);
    GreenPanel.Name = "GreenPanel";
    GreenPanel.Size = new Size(OrangePanel.Width - 24, OrangePanel.Height - (f3.Bottom + 6 + 12));
    GreenPanel.TabIndex = 1;
    OrangePanel.Controls.Add(GreenPanel);

    // PurplePanels
    PurplePanels = new List<Panel>();
    for (int i = 0; i < 10; i++)
    {
        Panel PurplePanel = new Panel();
        PurplePanel.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;

        PurplePanel.BackColor = Color.Purple;
        PurplePanel.Size = new Size(GreenPanel.Width - 24, 32 + 24);
        PurplePanel.Location = new Point(12, 6 + (i * (32 + 24 + 6)));
        PurplePanel.Name = "PurplePanel" + i.ToString();
        PurplePanel.TabIndex = i;

        // Fields
        TextBox fi = new TextBox();
        fi.Text = "Purple Panel " + i.ToString();
        fi.Anchor = f1.Anchor;
        fi.Font = f1.Font;
        fi.Location = f1.Location;
        fi.Name = "Fieldi" + i.ToString();
        fi.Size = new Size(PurplePanel.Width - 24, f1.Height);
        fi.TabIndex = 0;
        PurplePanel.Controls.Add(fi);

        GreenPanel.Controls.Add(PurplePanel);
        PurplePanels.Add(PurplePanel);
    }

    ResumeLayout(false);
    PerformLayout();
}

To see what is different with the FlowLayoutPanel, simply un-comment the relevant lines in the Green Panel section, and comment out the "GreenPanel = new Panel();" line. There you will see that FlowDirection.LeftToRight does not produce the desired result.

I also want to give a shout out to @Jimi and @LarsTech for pointing me in the right direction.

0
Joe On

general notice related to this topic:

Consider container A with autoscoll contains container B. Container B is not docked, autosize = true. You dynamically add content to B, awaiting B will grow up and container A shows scroll bar. But it's not happening.

In this case check B has max 2 anchors defined instead all of them (Anchor.Left | Anchor.Top | Anchor.Bottom | Anchor.Right)