Click here to Skip to main content
Click here to Skip to main content

Tagged as

Vertical collapsible Group Box Step by Step

, 24 Jan 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
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.

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.

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.

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

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.

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.

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

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.
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.
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.
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.

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)

Share

About the Author

Nasir M@hmood
Software Developer (Senior)
Pakistan Pakistan
No Biography provided

Comments and Discussions

 
QuestionDockStyle.Fill issue Pinmemberalex_kl10-Sep-12 23:08 
AnswerRe: DockStyle.Fill issue PinmemberNasir M@hmood11-Sep-12 19:50 
GeneralRe: DockStyle.Fill issue Pinmemberalex_kl12-Sep-12 3:42 
GeneralMy vote of 5 PinmemberKendoTM3-Feb-12 2:34 
QuestionExcellent! PinprotectorMarc Clifton25-Jan-12 3:18 
AnswerRe: Excellent! PinmemberNasir M@hmood27-Jan-12 4:21 
GeneralMy vote of 4 PinmemberSelvin24-Jan-12 6:38 
GeneralRe: My vote of 4 PinmemberNasir M@hmood30-Jan-12 19:17 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150327.1 | Last Updated 24 Jan 2012
Article Copyright 2012 by Nasir M@hmood
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid