Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to hide and show panels on a form and have it resize to take up slack?

Tags:

c#

.net

winforms

I have a form with three panels. I want the top two to be a fixed height, and bottom one to fill the rest of the space. The dialog is resizable, so all should change width on resixze, and bottom one should change height. This is important, the user must be able to stretch the form, as well as the program through code.

If I set a panel to visible = false, I want the form height to shrink so the others stay the same height. If I set a panel to visible = true, I want the form height to grow by the height of the panel.

I will control the hiding/showing of the panels with buttons. The idea is I show certain panels for "advanced" mode in my form, and hide them for "simple" mode. I cannot have a bunch of blank space if I hide a panel, and I want the form to shrink a bunch for simple mode.

I tried doing this with panels docked to top, but a form resize by the user will not change a panel height. So that is the main trick I am asking for help on.

like image 744
jmaeding Avatar asked Jan 02 '14 23:01

jmaeding


4 Answers

Anyone in this kind of situation can use the below styling:

  1. Use 2-3 Panel to Group different Controls and place them in a single parent control say a GroupBox.

  2. Make all the child panels Dock to the same side say "Top".

  3. if any of the panel is jumping over another due to similar docking. In Visual Studio, go to menu View > Other Windows > Document Outline and Set the display order. (https://msdn.microsoft.com/en-us/library/46xf4h0w%28v=vs.80%29.aspx)
  4. Set the Panel property as follows: AutoSize: true AutoSizeMode: GrowAndShrink

Once the panel is not visible, other panel will take away the empty space.

Hope this helps!!!

like image 97
DevCod Avatar answered Oct 26 '22 22:10

DevCod


the other posts are close, there is a detail missing that I included in the solution I came up with. Its a flag to tell if the sized event was caused by a user form resize, or the program doing it when a panel is shown or hidden.

For this solution, make a form with 4 panels. Set dock to top for all panels. Do not set any autosizing for panels or form. Also make two buttons and place on top panel, or any panel that you will not be hiding.

The code below shows how to handle the resized event, and the showing hiding buttons. I made them hide/show panel 2, but the code should work for any panel.

namespace ProgTesting {
public partial class Form5 : Form {
private bool doNothing = false;

public Form5() {
  InitializeComponent();
  cmdAdvanced.Visible = false;
}

private void cmdSimple_Click(object sender, EventArgs e) {
  if (panel2.Visible) {
    panel2.Visible = false;
    doNothing = true;
    this.MinimumSize = new Size(this.Width, this.Height - panel2.Height);
    this.Height = this.Height - panel2.Height;
    doNothing = false;
    cmdSimple.Visible = false;
    cmdAdvanced.Visible = true;
  }
}

private void cmdAdvanced_Click(object sender, EventArgs e) {
  if (!panel2.Visible) {
    panel2.Visible = true;
    doNothing = true;
    this.Height = this.Height + panel2.Height;
    this.MinimumSize = new Size(this.Width, this.Height);
    doNothing = false;
    cmdAdvanced.Visible = false;
    cmdSimple.Visible = true;
  }
}

private void Form5_SizeChanged(object sender, EventArgs e) {
  if (!doNothing)
    if (panel2.Visible)
      panel3.Height = this.ClientSize.Height - panel1.Height - panel2.Height - panel4.Height;
    else
      panel3.Height = this.ClientSize.Height - panel1.Height - panel4.Height;
}
}
}

You do have to manage the heights going on, which is a pain but gives you control. Some shots of it working: Form working

like image 38
jmaeding Avatar answered Oct 26 '22 22:10

jmaeding


It sounds like what you are looking for is an Expander. Essentially a control that consists of a header and a content area, where clicking on the header toggles the content area between visible and collapsed.

I'm not 100% certain if an Expander control will automatically adjust the height of a form when it expands/collapses though. You may need to hook up an event handler to the Expander to manually adjust the height of your form when the Expander collapses.

Try looking at the Stack Overflow Question Add an expander (collapse/expand) to a Panel WinForm. There are a number of links from that question about implementing an Expander in Windows Forms, including some that provide full source code.

Update:

I've knocked up a quick demo that will accomplish what you want, in a very primitive way, not using any of the various Expander controls out there. I think that while you will find the Expanders useful, I doubt they will adjust the size of the container they are inside, unless you write some adjustment code like I have below.

Create a form that looks like this:

Toggleable Panel Form

  • The two text boxes are anchored Left, Top, Right.
  • The toggle button is anchored Left, Top, named btnTogglePanel.
  • The magenta panel is anchored Left, Top, Right, Bottom, named pnlToggled.
  • The bottom button is anchored Right, Bottom.

Then in the code behind for the form:

public partial class ToggleableExpanderForm : Form
{
    public ToggleableExpanderForm()
    {
        InitializeComponent();
        SizeChanged += (s, args) => 
        {  
            if (_LastSize.HasValue)
            {
                var diff = Size - _LastSize.Value;
                if (_LastHeight.HasValue
                    && !IgnoreNextResizeForLastHeightAdjustment)
                {
                    _LastHeight += diff.Height;
                }
            }

            _LastSize = Size;
        };
    }

    private Size? _LastSize;
    private bool IgnoreNextResizeForLastHeightAdjustment = true;
    private int? _LastHeight;

    private void btnTogglePanel_Click(object sender, EventArgs e)
    {
        var newVisibility = !pnlToggled.Visible;
        int heightAdjustment = 0;

        if (newVisibility)
        {
            if (_LastHeight.HasValue)
            {
                heightAdjustment = _LastHeight.Value;
                _LastHeight = null;
            }
        }
        else
        {
            _LastHeight = pnlToggled.Height;
            heightAdjustment = -pnlToggled.Height;
        }

        pnlToggled.Visible = newVisibility;
        IgnoreNextResizeForLastHeightAdjustment = true;
        Height += heightAdjustment;
    }
}

Essentially you adjust the height of the form manually when the toggle button is clicked, based on whether or not the panel is hiding/showing. You also need to take into account of what will happen when the user resizes the form when the panel is invisible, which is where the cruft around listening to the SizeChanged event comes in. You need the answer to "how MUCH has the size changed" and then you adjust your previously stored panel height as appropriate.

I don't imagine the above code is perfect, and I haven't tested it in every use case, but it gets the basic job done.

like image 32
Todd Bowles Avatar answered Oct 26 '22 22:10

Todd Bowles


One way to go about it is to use a TableLayoutPanel for the top two panels.

The steps below will give you the resizing desired when the user resizes the form.

  1. Start by created a TableLayoutPanel (TLP) and shrink it down from the default 2 columns, 2 rows to just 2 columns, 1 row.
  2. Anchor it to Top, Left, and Right
  3. Now size the TLP to fit your top two panels and place each panel in a cell of the TLP.
  4. Anchor these two panels to all sides.
  5. Position the 3rd panel (Panel3) below the TLP to your liking and anchor it to all sides.

To handle the hiding of Panel3 some logic will need to be added to the appropriate button_Click event. Determine what size you would like the "minimized" height to be and then just store the form size when Panel3 is visible and restore the height when it's clicked again. It should look something like this.

private void button1_Click(object sender, EventArgs e)
{   
    if (panel3.Visible)
    { 
        // make invisible
        panel3.Visible = false;

        // storedHeight is a private member of the Form
        storedHeight = Form1.ActiveForm.Height;
        Form1.ActiveForm.Height = minimumHeight;  // Set to predetermined minimum height 
     }
     else
     {
         // make visible
         panel3.Visible = true;
         Form1.ActiveForm.Height = storedHeight;
     }
}

Now when you hide Panel3 the form will shrink to the size of the TLP, then grow again when Panel3 is visible. Also the top panels will expand in width, but not height. You will need to change the MinSize properties of the form and its value will have to be dynamically adjusted depending on whether Panel3 is visible or not.

like image 25
jmstoker Avatar answered Oct 26 '22 22:10

jmstoker