Click here to Skip to main content
15,884,537 members
Articles / Desktop Programming / Windows Forms

Vertical collapsible Group Box Step by Step

Rate me:
Please Sign up or sign in to vote.
4.81/5 (8 votes)
24 Jan 2012CPOL2 min read 31.5K   905   15   8
Vertical collapsible Group Box
VerticalGroupBox

Introduction

This is my first article and also I am not a professional writer so pardon me for my poor English and poor article writing.

Many times we want to cover much information on small space because user wants to see more information on single form without scrolling. That’s why collapsible control comes in mind. Here is little effort to make such control which collapse vertically.

Before Reading

This is step by step guide to achieve this goal. You will see repeating function and property declarations, new changes in these functions or properties are mark bold while new one are with normal font.

Step 1

In first step we will draw group box and image on top left corner of group box.

Declare variables like this. That’s mean initially our control will be expanded. Also declare image rectangle bounds.

C#
private bool _iscollapsed = false;
private Rectangle _buttonrect=new Rectangle(0,14,11,11);
public bool IsCollapsed
{
   get { return _iscollapsed; }            
}
private Rectangle ButtonRect
{
   get { return _buttonrect; }
} 

Make a new function which is responsible for drawing group box .First of all reposition new rectangle so that our image is in middle of left line. Then draw group box using GroupBoxRenderer.DrawGroupBox function.

C#
void DrawGroupBox(Graphics g)
{            
   Rectangle bounds = new Rectangle(ClientRectangle.X+4, ClientRectangle.Y + 6, ClientRectangle.Width-4, ClientRectangle.Height-6);
   GroupBoxRenderer.DrawGroupBox(g, bounds, Enabled ? GroupBoxState.Normal : GroupBoxState.Disabled);
}

Another function which is responsible for drawing image.

C#
private void DrawButton(Graphics g)
{
   if (IsCollapsed)
      g.DrawImage(Properties.Resources.plus, ButtonRect);
   else
      g.DrawImage(Properties.Resources.minusver, ButtonRect);
}

And call these function in Paint function like this

C#
protected override void OnPaint(PaintEventArgs pe)
{            
   DrawGroupBox(pe.Graphics);
   DrawButton(pe.Graphics);            
}

Now see the result after completing this step.

step1.png

Step 2

In this step we will add vertical text to group box

Add a StringFormat variable and set text direction to vertical. Also define a SolidBrush create new on first call and reuse it and dispose at end.

C#
private StringFormat format = new StringFormat(StringFormatFlags.DirectionVertical);
private SolidBrush _drawBrush = null;
private SolidBrush DrawBrush
{
   get
   {
      if (_drawBrush == null)
         return _drawBrush = new SolidBrush(Color.FromArgb(0, 70, 213));
      else
         return _drawBrush;
   }
}

Calculate string width in DrawGroupBox function and call DrawString function to draw string on left line of box.

C#
void DrawGroupBox(Graphics g)
{            
   Rectangle bounds = new Rectangle(ClientRectangle.X+4, ClientRectangle.Y + 6, ClientRectangle.Width-4, ClientRectangle.Height-6);
   GroupBoxRenderer.DrawGroupBox(g, bounds, Enabled ? GroupBoxState.Normal : GroupBoxState.Disabled);
   
   StringFormat sf = new StringFormat();
   int i_textPos = (bounds.X + 8) + ButtonRect.Width + 2;
   int i_textSize = (int)g.MeasureString(Text, this.Font).Width;
   i_textSize = i_textSize < 1 ? 1 : i_textSize;
   int i_endPos = i_textPos + i_textSize + 1;
           
   g.DrawString(Text, this.Font, DrawBrush, ButtonRect.X-4,ButtonRect.Y+15,format);
}

Now see the result after completing this step.

step2.png

Step 3

In this Step we will cover two tasks (1) make image to live i.e this will work like a button (2) make group box as a collapsible box

C#
private int _actualwidth = 0;
private int _currentwidth = 0;
private int _collapsewidth = 20;
private int CollapseWidth
{
   get { return _collapsewidth; }
}
private int ActualWidth
{
   get { return _actualwidth; }
   set { _actualwidth = value; }
}
private int CurrentWidth
{
   get { return _currentwidth; }
   set { _currentwidth = value; }
}
public bool IsCollapsed
{
   get { return _iscollapsed; }
   set
   {
      _iscollapsed = value;
      if (!value)
      {                    
         Width = ActualWidth;
      }
      else
         Width = CollapseWidth;         
      Invalidate();
   }
}
protected override void OnPaint(PaintEventArgs pe)
{
   if (ActualWidth == 0)
      ActualWidth = Width;
   DrawGroupBox(pe.Graphics);
   DrawButton(pe.Graphics);            
}
Override OnMouseUp to capture if click performed inside image if yes then call Collapsed change function and toggle its current state.
C#
private void CollapsedChanged()
{
   IsCollapsed = !IsCollapsed;            
}

protected override void OnMouseUp(MouseEventArgs e)
{
   if (ButtonRect.Contains(e.Location))
   {                
      CollapsedChanged();
   }
   base.OnMouseUp(e);
}
Now see the result after completing this step.

step3.png

Step 4

In this step we will beautify our control. If we see there is line under text which looks ugly lets remove it. Also override OnResize function and adjust its actual width it is helpful when our control size change.
C#
void DrawGroupBox(Graphics g)
{            
   Rectangle bounds = new Rectangle(ClientRectangle.X+4, ClientRectangle.Y + 6, ClientRectangle.Width-4, ClientRectangle.Height-6);
   GroupBoxRenderer.DrawGroupBox(g, bounds, Enabled ? GroupBoxState.Normal : GroupBoxState.Disabled);
   
   StringFormat sf = new StringFormat();
   int i_textPos = (bounds.X + 8) + ButtonRect.Width + 2;
   int i_textSize = (int)g.MeasureString(Text, this.Font).Width;
   i_textSize = i_textSize < 1 ? 1 : i_textSize;
   int i_endPos = i_textPos + i_textSize + 1;
   g.DrawLine(SystemPens.Control, ButtonRect.X+4, ButtonRect.Y + 15, ButtonRect.X+4, i_endPos);                    
   g.DrawString(Text, this.Font, DrawBrush, ButtonRect.X-4,ButtonRect.Y+15,format);
}
protected override void OnResize(EventArgs e)
{
   if (ActualWidth == 0)
      ActualWidth = Width;
   base.OnResize(e);
}

Step 5

In this step we will add event support, when collapse change event will trigger which we can use to perform actions in parent form.
C#
public delegate void CollapseChangeEventHandler(object sender);
public event CollapseChangeEventHandler OnCollapsedChanged;
private void CollapsedChanged()
{
   IsCollapsed = !IsCollapsed;
   if (OnCollapsedChanged != null)
      OnCollapsedChanged(this);
}

Step 6

Now our control is almost ready but there is a problem when we collapse box, controls which are left align still visible like this.

step51.png

This problem can be solved by setting visible property of all controls inside this control, but what about controls which are initially hidden. They will also be shown by this approach so solution for this problem is maintaining control visible state like this.

C#
private List<control> _visiblectrls = new List<control>();
public bool IsCollapsed
{
   get { return _iscollapsed; }
   set
   {
      _iscollapsed = value;
      if (!value)
      {                    
         Width = ActualWidth;
      }
      else
         Width = CollapseWidth;
      foreach (Control c in _visiblectrls)
      {
         c.Visible = !value;
      }        
      Invalidate();
   }
}
protected override void OnLayout(LayoutEventArgs levent)
{
   if (_visiblectrls.Count == 0)
   {
      foreach (Control c in Controls)
      {
         if (c.Visible)
            _visiblectrls.Add(c);
      }
   }
   base.OnLayout(levent);
}
</control>

Now see the final results
step52.png

Hidden Button is initially hidden.

step53.png

step54.png

That’s end of our work. Many Thanks to read this artical.

History

First Version 24th january 2012.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Pakistan Pakistan
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionDockStyle.Fill issue Pin
alex_kl10-Sep-12 22:08
alex_kl10-Sep-12 22:08 
AnswerRe: DockStyle.Fill issue Pin
Nasir M@hmood11-Sep-12 18:50
Nasir M@hmood11-Sep-12 18:50 
GeneralRe: DockStyle.Fill issue Pin
alex_kl12-Sep-12 2:42
alex_kl12-Sep-12 2:42 
GeneralMy vote of 5 Pin
KendoTM3-Feb-12 1:34
KendoTM3-Feb-12 1:34 
QuestionExcellent! Pin
Marc Clifton25-Jan-12 2:18
mvaMarc Clifton25-Jan-12 2:18 
AnswerRe: Excellent! Pin
Nasir M@hmood27-Jan-12 3:21
Nasir M@hmood27-Jan-12 3:21 
GeneralMy vote of 4 Pin
Selvin24-Jan-12 5:38
Selvin24-Jan-12 5:38 
GeneralRe: My vote of 4 Pin
Nasir M@hmood30-Jan-12 18:17
Nasir M@hmood30-Jan-12 18:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.