Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Collapse 'button' for splitcontainer control

I'm using Microsoft's SplitContainer control in my WinForms desktop application.

I'd like to have a small button (or any nice UI element) between the panels of the splitter control to collapse one of the panels. E.g. a 'button' with two parts, if I click one part, the right side panel collapses, if I click on the other part, the left side panel collapses.

Is this possible? How could that be implemented?

like image 502
Tom Avatar asked Jun 16 '11 23:06

Tom


3 Answers

You will have to write your own event for that. You have to decide the design. Hope you need something like below.

private void radButton1_Click(object sender, EventArgs e) 
{ 
    splitPanel1.Collapsed = !splitPanel1.Collapsed; 
}

EDIT 1

There is no easy way as you think. Have a look here and here to get an idea.

EDIT 2

You can add two toolStrips to both panels which are Dock:Top and add two buttons as in the below image which looks quite good. Just a thought...

enter image description here

Edit3

Splitter is another option for you. Have a look here.

like image 115
CharithJ Avatar answered Nov 01 '22 07:11

CharithJ


I have used this solution in my implementation, it's probably too late for you but might help other people.

In my implementation I also moved controls from one panel to another, that's why I'm only changing the panel collapsed state as the last action.

Since I can't post any images, just try to figure it out according to the following diagram ( the [<] and [>] are the buttons):

 ╔════════════╤═════════════╗
 ║         [<]│[>]          ║ 
 ║            │             ║ 
 ║            │             ║ 
 ║            │             ║ 
 ║            │             ║ 
 ║            │             ║ 
 ╚════════════╧═════════════╝

Following is the implementation for the left panel (panel1), a similar function is also used for the right panel.

    private void setSplitterLeftPanelCollapsedState(bool collapse)
    {
        splitContainer1.SuspendLayout();

        // Collapse the left panel
        if (collapse)
        {
            if (!splitContainer1.Panel1Collapsed)
            {
                // restoring the panel in the end to apply layout changes
                buttonOpenPanel1.Text = ">";
                splitContainer1.Panel1Collapsed = true;
            }
        }
        // Open the left panel
        else
        {
            if (splitContainer1.Panel1Collapsed)
            {
                // collapsing the panel in the end to apply layout changes
                buttonOpenPanel1.Text = "<";
                splitContainer1.Panel1Collapsed = false;
            }
        }

        splitContainer1.ResumeLayout();

        comboBoxSearchText.Focus();
    }
like image 24
Ying Avatar answered Nov 01 '22 07:11

Ying


Inspired by the layout of Lotus Notes, I designed something that I think would be useful in this situation. It only contains one button between the panels which toggles expand/collapse state of a single panel but can easily be modified to use two buttons to control both the right and left panels. It uses two split containers, one docked inside the other, and the mouseMove event of the “middle” panel to simulate dragging a splitter (Moving a control by dragging it with the mouse in C#). Additionally, I use the ClientSizedChanged event of the containers to handle the logic of toggling button images instead of the method which collapses/expands the panel (Detect when SplitContainer collapsed changes).

Design:

splitContainer1
╔════════════╤═════════════════════════════════╗
║            │ splitContainer2 (docked fill)   ║
║            │ ╔════════════╤════════════════╗ ║
║            │ ║            │                ║ ║
║            │ ║ Button(s)  │                ║ ║
║            │ ║ [<>]       │                ║ ║
║            │ ║            │                ║ ║
║            │ ╚════════════╧════════════════╝ ║
╚════════════╧═════════════════════════════════╝

splitContainer2.Dock = DockStyle.Fill;
splitContainer1 = splitContainer2.IsSplitterFixed = true;
splitContainer2.Panel1.Cursor = Cursors.VSplit;

Anchor button left or right(or dock several buttons inside an tableLayout control) . Just make sure there is still some part of the panel available to click/drag on.
Set the maximum with of the middle panel to a low number. Size depends on how wide you need your buttons to be.

Code:

Panel will switch to opposite state
If you really need one button with two parts instead of two buttons or a toggle button you would need to get the mouse coordinates clicked and have differnt logic depending on where the click occured.

private void btnExpand_Click(object sender, EventArgs e)
{
    splitContainer1.Panel1Collapsed = !splitContainer1.Panel1Collapsed;  
}

Handel logic associated with the expand/collapse. I chose to use this event because there are several ways in my program the user can collapse/expand panels.

    private void splitContainer1_Panel2_ClientSizeChanged(object sender, EventArgs e)
    {

        if (splitContainer1.Panel1Collapsed)
        {
            splitContainer2.Panel1.Cursor = Cursors.Default;
            this.btnExpand.Image =  imageExpand;
        }
        Else
       {
            splitContainer2.Panel1.Cursor = Cursors.VSplit;
            this.btnExpand.Image = imageCollapse;
      }
    }

Handel the resizing of the panels due to moving the faux splitter

    private void splitContainer2_Panel1_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {

    /* All you really need is this:
                splitContainer1.SplitterDistance += e.X;  

    Note: Splitter distance must be a positive integer and e.X will be negitive when dragging to the left of the splitContainer. You could handel this check here or on the splitterMoving event.

        The code I have below shows how to “snap” a panel closed if the splitter is moved close enough to the edge 
    Or prevent a panel from being hidden from view (which could also be accomplished by setting the minimum size of a panel). 

    */

            if (e.X + splitContainer1.SplitterDistance < 40)
            {

               while (splitContainer1.SplitterDistance > 1)
                    splitContainer1.SplitterDistance--;
                splitContainer1.Panel1Collapsed = true;

            }
            else if ((e.X + splitContainer1.SplitterDistance) * 1.00 / this.Width * 1.00 < .75)
                splitContainer1.SplitterDistance += e.X;  
            else
                Cursor.Current = Cursors.No;


        }
}
like image 2
Jayden67 Avatar answered Nov 01 '22 06:11

Jayden67