In part 1 of this series, I went over how to actually establish the tree layout that would be used to create an organizational chart using C#.

Now that we have established we have a loaded tree structure, we simply need to build the chart itself.

To simplify the explanation of this process, I have broken the drawing out into two sections.

The first section, BuildBlock, simply builds the actual block which will have each Employee’s name and title information, with a background color and a small black border around the outside. By breaking this out of the process, it makes the code much easier to follow.

I will comment inline in the method, so here is the code for BuildBlock:

// We want to return a bitmap of each Employee class
private Bitmap BuildBlock(Employee employee)
  int width = 250;
  int height = 80;

  // Create a new Bitmap which is is specified by the height and width above
  Bitmap canvas = new Bitmap(width, height);

  // Create a drawable Graphics object from the bitmap
  Graphics gfx = Graphics.FromImage(canvas);

  // Fill the rectangle with a background of gray
  gfx.FillRegion(Brushes.Gray, new Region(new Rectangle(0, 0, width, height)));

  // Draw the border around the outside
  gfx.DrawRectangle(new Pen(Brushes.Black, 1), new Rectangle(0, 0, width - 1, height - 1));

  // Establish our two font objects, for the name and title respectively
  Font fontname = new Font("Helvetica", 14, FontStyle.Bold, GraphicsUnit.Pixel);
  Font fonttitle = new Font("Helvetica", 10, FontStyle.Italic, GraphicsUnit.Pixel);

  int namewidth = 0;
  int nameheight = 0;
  int titlewidth = 0;
  int titleheight = 0;

  // Get the height and widths of each text blob, with their fonts, so we can center them in the block
  namewidth = (int)gfx.MeasureString(employee.Name, fontname).Width;
  nameheight = (int)gfx.MeasureString(employee.Name, fontname).Height;
  titlewidth = (int)gfx.MeasureString(employee.Title, fonttitle).Width;
  titleheight = (int)gfx.MeasureString(employee.Title, fonttitle).Height;

  int namex = 0;
  int namey = 0;
  int titlex = 0;
  int titley = 0;

  // Now determine the center for names and titles with the widths and heights of the title and name font sections
  namex = (width / 2) - (namewidth / 2);
  namey = (height / 2) - ((nameheight + titleheight) / 2);
  titlex = (width / 2) - (titlewidth / 2);
  titley = (height / 2) - ((nameheight + titleheight) / 2) + nameheight;

  // Draw the actual text
  gfx.DrawString(Name, fontname, Brushes.DarkBlue, namex, namey);
  gfx.DrawString(Title, fonttitle, Brushes.Black, titlex, titley);

  // Flush the output to the bitmap

  // Establish a padding bitmap, which will have 10 pixels around the entire image
  // Padding makes it look much better so they are not cramping and allows for easier drawing of lines
  Bitmap padding = new Bitmap(width + 20, height + 20);

  // Make a graphics object from the padding bitmap
  Graphics padGfx = Graphics.FromImage(padding);

  // Center the image in the padding canvas
  padGfx.DrawImage(canvas, new Point(10, 10));

  // Flush the output to the bitmap
  return padding;

The second aspect of drawing the tree, is drawing the entire tree itself. If you look at the structure of a tree, each tree is really a branch, even the tree itself, from the larger aspect.

To make the drawing logical and much easier to understand, if you break each grouping into a branch, you can then apply logic to each branch and traverse upwards until your tree is complete.

The aptly named BuildBranch is the real “meat” of our organizationl chart builder, so without further ado, here is the recursive code:

private Bitmap BuildBranch(Employee Manager)
  // In each case of BuildBranch, Manager is really just the parent of all the children

  // Get the block of the manager
  Bitmap manager = BuildBlock(Manager);

  // Now do the same for each child, obtaining a list of all Bitmap children
  List<Bitmap> children = new List<Bitmap>();
  foreach (Employee reportee in Manager.Children)

  int canvasWidth = 0;
  int canvasHeight = 0;

  // Figure out your final heights and widths
  // Do not forget that a branch could also just be a single employee without any children,
  // essentially rendering a branch the same as a block
  if (children.Count > 0)
    foreach (Bitmap child in children)
      canvasHeight += child.Height;
      canvasWidth = manager.Width;

    // Always increase the height by the manager
    canvasHeight += manager.Height;
    canvasWidth = manager.Width;
    canvasHeight = manager.Height;

  // Create the bitmap to the correct size
  Bitmap result = new Bitmap(canvasWidth, canvasHeight);

  // Now create a Graphics object from that bitmap
  Graphics gfx = Graphics.FromImage(result);

  // Center the manager in the entire branch image
  int managerx = (canvasWidth / 2) - (manager.Width / 2);

  // If the manager has children, then you want to draw a line down to connect the branches below
  if (children.Count > 0)
    Graphics liner = Graphics.FromImage(manager);
    liner.DrawLine(new Pen(Brushes.Black, 2), new Point(manager.Width / 2, 90), new Point(manager.Width / 2, 100));

  // Draw a line from the center of the manager up (to connect to the next block)
  Graphics liner = Graphics.FromImage(manager);
  liner.DrawLine(new Pen(Brushes.Black, 2), new Point(manager.Width / 2, 0), new Point(manager.Width / 2, 10));

  gfx.DrawImage(manager, new Point(managerx, 0));

  // Draw lines in between org levels to connect each child to the manager
  int childx = 0;
  foreach (Bitmap child in children)
    gfx.DrawImage(child, new Point(childx, manager.Height));
    gfx.DrawLine(new Pen(Brushes.Black, 2), new Point(childx + (child.Width / 2), manager.Height), new Point(managerx + (manager.Width / 2), manager.Height));
    childx += child.Width;

  // Dump the graphics object to the bitmap

  // Give us the full Org Chart!
  return result;

That’s it, now you have your organizational chart!