Creating a Family Tree Using .NET

Introduction

Today, you will learn how easy it is to create a simple family tree in .NET.

Family Trees and Genograms

A family tree is a chart that represents family relationships in a tree structure. A genogram is a pictorial display of a person’s family relationships and medical history. The difference between a genogram and a family tree is that a genogram allows the user to visualize hereditary patterns and psychological factors that punctuate relationships.

To create a family tree, I needed some photos of my family. Unfortunately, I do not have many, so I opted to cover a different family instead.

Ancient Egypt

How good is your history?

Ancient Egypt was a civilization of ancient Northeastern Africa along the lower Nile River. It is now known as Egypt. The ancient Egyptian civilization coalesced around 3100 B.C. with the political unification of Upper and Lower Egypt. The history of ancient Egypt occurred as a series of stable kingdoms, separated by Intermediate Periods (periods of relative instability): the Old Kingdom (Early Bronze Age), the Middle Kingdom (Middle Bronze Age), and the New Kingdom (Late Bronze Age).

Fourth Dynasty of Egypt

The Fourth Dynasty of ancient Egypt is also known as the “golden age” of the Old Kingdom. The Fourth Dynasty lasted from 2613 to 2494 B.C. This, the Age of the Pyramids, was a time of peace and prosperity and a time where trade with other countries is started.

The Fourth Dynasty heralded the height of the pyramid-building age. No other period in Egypt’s history equaled The Fourth Dynasty’s architectural accomplishments.

Enough history. I love Ancient Egypt and have studied it a while back for a book project which I was busy with (and still am…)

Practical

To create a Family Tree, you need to extend the capabilities of the built-in Windows PictureBox object. More on this later. Create a new C# or VB Windows Forms project. Resize the Form and add a Docked PictureBox and a StatusStrip onto it. The Design resembles Figure 1.

Design
Figure 1: Design

Add a new Interface, name it IDrawable, and add the following code into it.

C#

using System.Drawing;

namespace FamilyTree_C
{
   interface IDrawable
   {

      SizeF GetSize(Graphics gr, Font fFont);

      bool Point(Graphics gr, Font fFont, PointF ptCentre,
         PointF ptTarget);

      void Draw(float x, float y, Graphics gr, Pen pen,
         Brush BackBrush, Brush Brush, Font fFont);
   }
}

VB.NET

Imports System.Drawing

Interface IDrawable

   Function GetSize(ByVal gr As Graphics, ByVal fFont As Font) _
      As SizeF

   Function Point(ByVal gr As Graphics, ByVal fFont As Font, _
      ByVal ptCentre As PointF, ByVal ptTarget As PointF) _
      As Boolean

   Sub Draw(ByVal x As Single, ByVal y As Single, _
      ByVal gr As Graphics, ByVal pen As Pen, ByVal BackBrush _
      As Brush, ByVal Brush As Brush, ByVal fFont As Font)

End Interface

The Draw sub, GetSize, and Point methods get created here. Make use of this Interface in the PicNode Class that you should add next.

C#

using System.Drawing;
using System.Windows.Forms;

namespace FamilyTree_C
{
   class PicNode : IDrawable
   {
      public Image Pic = null;

      public string Desc;

      public bool Sel = false;

      public PicNode(string desc, Image pic)
      {

         Desc = desc;
         Pic = pic;

      }

      public SizeF NodeSize = new SizeF(100, 100);

      public SizeF GetSize(Graphics gr, Font fFont)
      {

         return NodeSize;

      }

      private RectangleF Loc(PointF ptCentre)
      {

         return new RectangleF(ptCentre.X - NodeSize.Width / 2,
            ptCentre.Y - NodeSize.Height / 2, NodeSize.Width,
            NodeSize.Height);

      }

      public bool Point(Graphics gr, Font font, PointF ptCentre,
         PointF ptTarget)
      {

         RectangleF rect = Loc(ptCentre);

         return rect.Contains(ptTarget);
      }


      public void Draw(float x, float y, Graphics gr, Pen pen,
         Brush backbrush, Brush brush, Font font)
      {
         RectangleF locrec = Loc(new PointF(x, y));

         Rectangle rect = Rectangle.Round(locrec);

         if (Sel)
         {

            gr.FillRectangle(Brushes.White, rect);

            ControlPaint.DrawBorder3D(gr, rect,
               Border3DStyle.Sunken);

         }
         else
         {

            gr.FillRectangle(Brushes.Orange, rect);

            ControlPaint.DrawBorder3D(gr, rect,
               Border3DStyle.Raised);

         }

         locrec.Inflate(-5, -5);

         locrec = Position(Pic, locrec);

         gr.DrawImage(Pic, locrec);
      }


      private RectangleF Position(Image pic, RectangleF rect)
      {
         float fWidth = pic.Width;
         float fHeight = pic.Height;

         float fCentre = fWidth / fHeight;
         float fRecCentre = rect.Width / rect.Height;
         float scale = 1;

         if (fCentre > fRecCentre)
         {

            scale = rect.Width / fWidth;

         }
         else
         {

            scale = rect.Height / fHeight;

         }

         fWidth *= scale;
         fHeight *= scale;

         RectangleF drawing_rect = new RectangleF(rect.X +
            (rect.Width - fWidth) / 2, rect.Y +
            (rect.Height - fHeight) / 2, fWidth, fHeight);

         return drawing_rect;
      }
   }
}

VB.NET

Imports FamilyTree_VB

Public Class PicNode
Implements IDrawable

   Public Pic As Image = Nothing

   Public Desc As String

   Public Sel As Boolean = False

   Public Sub New(ByVal desc As String, ByVal pic As Image)

      desc = desc
      pic = pic

   End Sub

   Public NodeSize As SizeF = New SizeF(100, 100)

   Public Function GetSize(ByVal gr As Graphics, _
         ByVal fFont As Font) As SizeF

      Return NodeSize

   End Function

   Private Function Loc(ByVal ptCentre As PointF) As RectangleF

      Return New RectangleF(ptCentre.X - NodeSize.Width / 2, _
         ptCentre.Y - NodeSize.Height / 2, NodeSize.Width, _
         NodeSize.Height)

   End Function

   Public Function Point(ByVal gr As Graphics, ByVal font _
         As Font, ByVal ptCentre As PointF, ByVal ptTarget _
         As PointF) As Boolean

      Dim rect As RectangleF = Loc(ptCentre)

      Return rect.Contains(ptTarget)

   End Function


   Public Sub Draw(ByVal x As Single, ByVal y As Single, _
         ByVal gr As Graphics, ByVal pen As Pen, ByVal backbrush _
         As Brush, ByVal brush As Brush, ByVal font As Font)

      Dim locrec As RectangleF = Loc(New PointF(x, y))

      Dim rect As Rectangle = Rectangle.Round(locrec)

      If Sel Then

         gr.FillRectangle(Brushes.White, rect)
         ControlPaint.DrawBorder3D(gr, rect, Border3DStyle.Sunken)

      Else

         gr.FillRectangle(Brushes.Orange, rect)
         ControlPaint.DrawBorder3D(gr, rect, Border3DStyle.Raised)

      End If

      locrec.Inflate(-5, -5)
      locrec = Position(Pic, locrec)
      gr.DrawImage(Pic, locrec)

   End Sub

   Private Function Position(pic As Image, rect As RectangleF) _
         As RectangleF

      Dim fWidth As Single = pic.Width
      Dim fHeight As Single = pic.Height

      Dim fCentre As Single = fWidth / fHeight
      Dim fRecCentre As Single = rect.Width / rect.Height
      Dim scale As Single = 1

      If fCentre > fRecCentre Then

         scale = rect.Width / fWidth

      Else

         scale = rect.Height / fHeight

      End If

      fWidth *= scale
      fHeight *= scale

      Dim drawing_rect As RectangleF = New RectangleF(rect.X + _
         (rect.Width - fWidth) / 2, rect.Y + _
         (rect.Height - fHeight) / 2, fWidth, fHeight)

      Return drawing_rect

   End Function

   Private Function IDrawable_GetSize(gr As Graphics, _
         fFont As Font) As SizeF Implements IDrawable.GetSize

      Throw New NotImplementedException()

   End Function

   Private Function IDrawable_Point(gr As Graphics, _
         fFont As Font, ptCentre As PointF, ptTarget As PointF) _
         As Boolean Implements IDrawable.Point

      Throw New NotImplementedException()

   End Function

   Private Sub IDrawable_Draw(x As Single, y As Single, _
         gr As Graphics, pen As Pen, BackBrush As Brush, _
         Brush As Brush, fFont As Font) Implements IDrawable.Draw

      Throw New NotImplementedException()

   End Sub

End Class

The PicNode class draws a box for each family member. Add the FamilyMember class.

C#

using System.Collections.Generic;
using System.Drawing;

namespace FamilyTree_C
{
   class FamilyMember<T> where T : IDrawable
   {
      public T Obj;

      public List<FamilyMember<T>> lstChildren = new
         List<FamilyMember<T>>();

      private const float fX = 5;
      private const float fY = 30;

      private PointF ptCenter;

      public Font fFont = null;

      public Pen pPen = Pens.Black;
      public Brush bBrush = Brushes.Red;
      public Brush bBackBrush = Brushes.White;

      public FamilyMember(T obj) : this(obj, new Font("Arial", 8))
      {

         Obj = obj;

      }
      public FamilyMember(T obj, Font fFont)
      {

         Obj = obj;
         this.fFont = fFont;

      }

      public void Add(FamilyMember<T> obj)
      {

         lstChildren.Add(obj);

      }

      public void Organize(Graphics gr, ref float X, ref float Y)
      {

         SizeF szObj = Obj.GetSize(gr, fFont);

         float x = X;
         float MaxY = Y + szObj.Height;
         float SubY = Y + szObj.Height + fY;

         foreach (FamilyMember<T> tChild in lstChildren)
         {

            float MinY = SubY;

            tChild.Organize(gr, ref x, ref MinY);

            if (MaxY < MinY) MaxY = MinY;
               x += fX;

         }

         if (lstChildren.Count > 0) x -= fX;

            float SubWidth = x - X;

         if (szObj.Width > SubWidth)
         {

            x = X + (szObj.Width - SubWidth) / 2;

            foreach (FamilyMember<T> tChild in lstChildren)
            {

               tChild.Organize(gr, ref x, ref SubY);

               x += fX;

            }

            SubWidth = szObj.Width;
         }

         ptCenter = new PointF(X + SubWidth / 2, Y +
            szObj.Height / 2);

         X += SubWidth;

         Y = MaxY;

      }

      public void DrawFamily(Graphics gr, ref float x, float y)
      {

         Organize(gr, ref x, ref y);

         DrawFamily(gr);

      }

      public void DrawFamily(Graphics gr)
      {

         DrawLinks(gr);

         DrawNodes(gr);

      }

      private void DrawLinks(Graphics gr)
      {

         if (lstChildren.Count == 1)
         {

            gr.DrawLine(pPen, ptCenter, lstChildren[0].ptCenter);

         }

         else if (lstChildren.Count > 1)
         {

            float xmin = lstChildren[0].ptCenter.X;
            float xmax = lstChildren[lstChildren.Count - 1]
               .ptCenter.X;

            SizeF my_size = Obj.GetSize(gr, fFont);

            float y = ptCenter.Y + my_size.Height / 2 + fY / 2f;

            gr.DrawLine(pPen, xmin, y, xmax, y);

            gr.DrawLine(pPen, ptCenter.X, ptCenter.Y,
               ptCenter.X, y);

            foreach (FamilyMember<T> tChild in lstChildren)
            {

               gr.DrawLine(pPen, tChild.ptCenter.X, y,
                  tChild.ptCenter.X, tChild.ptCenter.Y);

            }
         }

         foreach (FamilyMember<T> tChild in lstChildren)
         {

            tChild.DrawLinks(gr);

         }

      }

      private void DrawNodes(Graphics gr)
      {
         Obj.Draw(ptCenter.X, ptCenter.Y, gr, pPen, bBackBrush,
            bBrush, fFont);

         foreach (FamilyMember<T> tChild in lstChildren)
         {

            tChild.DrawNodes(gr);

         }
      }

      public FamilyMember<T> NodePoint(Graphics gr,
         PointF ptTarget)
      {
         if (Obj.Point(gr, fFont, ptCenter, ptTarget)) return this;

         foreach (FamilyMember<T> tChild in lstChildren)
         {

            FamilyMember<T> hit_node =
               tChild.NodePoint(gr, ptTarget);
            if (hit_node != null) return hit_node;

         }

         return null;

      }

      public bool Delete(FamilyMember<T> tTarget)
      {

         foreach (FamilyMember<T> tChild in lstChildren)
         {

            if (tChild == tTarget)
            {

               lstChildren.Remove(tChild);

               return true;

            }

            if (tChild.Delete(tTarget)) return true;

         }

         return false;

      }

   }

}

VB.NET

Imports System.Collections.Generic
Imports System.Drawing

Class FamilyMember(Of T As IDrawable)

   Public Obj As T

   Public lstChildren As List(Of FamilyMember(Of T)) = New _
      List(Of FamilyMember(Of T))()

   Private Const fX As Single = 5

   Private Const fY As Single = 30

   Private ptCenter As PointF

   Public fFont As Font = Nothing

   Public pPen As Pen = Pens.Black

   Public bBrush As Brush = Brushes.Red

   Public bBackBrush As Brush = Brushes.White

   Public Sub New(ByVal obj As T)

      obj = obj

   End Sub

   Public Sub New(ByVal obj As T, ByVal fFont As Font)

      obj = obj
      Me.fFont = fFont

   End Sub

   Public Sub Add(ByVal obj As FamilyMember(Of T))

      lstChildren.Add(obj)

   End Sub

   Public Sub Organize(ByVal gr As Graphics, ByRef X As Single, _
         ByRef Y As Single)

      Dim szObj As SizeF = Obj.GetSize(gr, fFont)
      Dim xX As Single = X

      Dim MaxY As Single = Y + szObj.Height
      Dim SubY As Single = Y + szObj.Height + fY

      For Each tChild As FamilyMember(Of T) In lstChildren

         Dim MinY As Single = SubY

         tChild.Organize(gr, X, MinY)

         If MaxY < MinY Then MaxY = MinY

         xX += fX

      Next

      If lstChildren.Count > 0 Then xX -= fX

      Dim SubWidth As Single = xX - xX

      If szObj.Width > SubWidth Then

         xX = xX + (szObj.Width - SubWidth) / 2

         For Each tChild As FamilyMember(Of T) In lstChildren

            tChild.Organize(gr, xX, SubY)
            xX += fX

         Next

         SubWidth = szObj.Width

      End If

      ptCenter = New PointF(xX + SubWidth / 2, Y + _
         szObj.Height / 2)

      xX += SubWidth
      Y = MaxY

   End Sub

   Public Sub DrawFamily(ByVal gr As Graphics, ByRef x As Single, _
         ByVal y As Single)

      Organize(gr, x, y)
      DrawFamily(gr)

   End Sub

   Public Sub DrawFamily(ByVal gr As Graphics)

      DrawLinks(gr)
      DrawNodes(gr)

   End Sub

   Private Sub DrawLinks(ByVal gr As Graphics)

      If lstChildren.Count = 1 Then

         gr.DrawLine(pPen, ptCenter, lstChildren(0).ptCenter)

      ElseIf lstChildren.Count > 1 Then

         Dim xmin As Single = lstChildren(0).ptCenter.X
         Dim xmax As Single = lstChildren(lstChildren.Count - 1) _
            .ptCenter.X
         Dim my_size As SizeF = Obj.GetSize(gr, fFont)
         Dim y As Single = ptCenter.Y + my_size.Height / 2 + _
            fY / 2.0F

         gr.DrawLine(pPen, xmin, y, xmax, y)
         gr.DrawLine(pPen, ptCenter.X, ptCenter.Y, ptCenter.X, y)

         For Each tChild As FamilyMember(Of T) In lstChildren

            gr.DrawLine(pPen, tChild.ptCenter.X, y, _
               tChild.ptCenter.X, tChild.ptCenter.Y)

         Next

      End If

      For Each tChild As FamilyMember(Of T) In lstChildren

         tChild.DrawLinks(gr)

      Next

   End Sub

   Private Sub DrawNodes(ByVal gr As Graphics)

      Obj.Draw(ptCenter.X, ptCenter.Y, gr, pPen, bBackBrush, _
         bBrush, fFont)

      For Each tChild As FamilyMember(Of T) In lstChildren

         tChild.DrawNodes(gr)

      Next

   End Sub

   Public Function NodePoint(ByVal gr As Graphics, ByVal ptTarget _
         As PointF) As FamilyMember(Of T)

      If Obj.Point(gr, fFont, ptCenter, ptTarget) Then Return Me

      For Each tChild As FamilyMember(Of T) In lstChildren

         Dim hit_node As FamilyMember(Of T) = _
            tChild.NodePoint(gr, ptTarget)

         If hit_node IsNot Nothing Then Return hit_node

      Next

      Return Nothing

   End Function

   Public Function Delete(ByVal tTarget As FamilyMember(Of T)) _
         As Boolean

      For Each tChild As FamilyMember(Of T) In lstChildren

         If tChild.Equals(tTarget) Then

            lstChildren.Remove(tChild)

            Return True

         End If

         If tChild.Delete(tTarget) Then Return True

      Next

      Return False
   End Function
End Class

The FamilyMember class gets all family members, along with their images and other properties. Then, it connects all members.

Inside the Form, Instantiate a Family Member:

C#

      private FamilyMember<PicNode> SelectedNode;

VB.NET

   Private SelectedNode As FamilyMember(Of PicNode)

Create a Sub procedure to Create the Tree.

C#

private void ShowTree()
{
   using (Graphics gr = picFamily.CreateGraphics())
   {

      float xmin = 0, ymin = 0;

      Unknown.Organize(gr, ref xmin, ref ymin);
      // HetepheresI.Organize(gr, ref xmin, ref ymin);
      // SNEFERU.Organize(gr, ref xmin, ref ymin);

      xmin = (this.ClientSize.Width - xmin) / 2;

      ymin = 10;

      Unknown.Organize(gr, ref xmin, ref ymin);

   }

   picFamily.Refresh();
}

VB.NET

   Private Sub ShowTree()

      Using gr As Graphics = picFamily.CreateGraphics()

         Dim xmin As Single = 0, ymin As Single = 0

         Unknown.Organize(gr, xmin, ymin)
         'HetepheresI.Organize(gr, xmin, ymin)'
         'SNEFERU.Organize(gr, xmin, ymin)'

         xmin = (Me.ClientSize.Width - xmin) / 2
         ymin = 10
         Unknown.Organize(gr, xmin, ymin)

      End Using

      picFamily.Refresh()

   End Sub

This tree can sprout from Queen Hetepheres I and King Sneferu, or from an Unknown entity. The Trees are loosely based on the Family Tree found here on Wikipedia.

Add the SelNode Sub procedure to determine which entity has been clicked.

C#

      private void SelNode(PointF pt)
      {

         if (SelectedNode != null)
         {

            SelectedNode.Obj.Sel = false;
            lblNodeText.Text = "";

         }

         using (Graphics gr = picFamily.CreateGraphics())
         {

            SelectedNode = HetepheresI.NodePoint(gr, pt);

         }

         if (SelectedNode != null)
         {

            SelectedNode.Obj.Sel = true;
            lblNodeText.Text = SelectedNode.Obj.Desc;

         }

         picFamily.Refresh();

      }

VB.NET

   Private Sub SelNode(ByVal pt As PointF)

      If SelectedNode IsNot Nothing Then

         SelectedNode.Obj.Sel = False
         lblNodeText.Text = ""

      End If

      Using gr As Graphics = picFamily.CreateGraphics()

         SelectedNode = HetepheresI.NodePoint(gr, pt)

      End Using

      If SelectedNode IsNot Nothing Then

         SelectedNode.Obj.Sel = True
         lblNodeText.Text = SelectedNode.Obj.Desc

      End If

      picFamily.Refresh()

   End Sub

Create the Root Family members.

C#

      private FamilyMember<PicNode> HetepheresI =  new
            FamilyMember<PicNode>(
         new PicNode("HetepheresI",
            Properties.Resources.Hetepheres_I));
         private FamilyMember<PicNode> SNEFERU =
            new FamilyMember<PicNode>(
         new PicNode("SNEFERU",
            Properties.Resources.SNEFERU));
         private FamilyMember<PicNode> Unknown =
            new FamilyMember<PicNode>(
         new PicNode("Unknown",
      Properties.Resources.Unknown));

VB.NET

   Private HetepheresI As FamilyMember(Of PicNode) = New _
      FamilyMember(Of PicNode)(New PicNode("HetepheresI", _
      My.Resources.Hetepheres_I))

   Private SNEFERU As FamilyMember(Of PicNode) = New _
      FamilyMember(Of PicNode)(New PicNode("SNEFERU", _
      My.Resources.SNEFERU))

   Private Unknown As FamilyMember(Of PicNode) = New _
      FamilyMember(Of PicNode)(New PicNode("Unknown", _
      My.Resources.Unknown))

In Form_Load, add the other family members and their positions.

C#

      private void Form1_Load(object sender, EventArgs e)
      {

         FamilyMember<PicNode> MerititesI =
         new FamilyMember<PicNode>(
            new PicNode("MerititesI",
               Properties.Resources.Meritites_I));
               FamilyMember<PicNode> KHUFU =
                  new FamilyMember<PicNode>(
                     new PicNode("KHUFU",
                        Properties.Resources.KHUFU));
               FamilyMember<PicNode> Henutsen =
                  new FamilyMember<PicNode>(
                     new PicNode("Henutsen",
                        Properties.Resources.Henutsen));
               FamilyMember<PicNode> Rahotep =
                  new FamilyMember<PicNode>(
                     new PicNode("Rahotep",
                        Properties.Resources.Rahotep));
               FamilyMember<PicNode> NefermaatI =
                  new FamilyMember<PicNode>(
                     new PicNode("NefermaatI",
                        Properties.Resources.Nefermaat_I));
               FamilyMember<PicNode> Itet =
                  new FamilyMember<PicNode>(
                     new PicNode("Itet",
                        Properties.Resources.Itet));

               FamilyMember<PicNode> Djedefhor =
                  new FamilyMember<PicNode>(
                     new PicNode("Djedefhor",
                        Properties.Resources.Djedefhor));
               FamilyMember<PicNode> Kawab =
                  new FamilyMember<PicNode>(
                     new PicNode("Kawab",
                        Properties.Resources.Kawab));
               FamilyMember<PicNode> HetepheresII =
                  new FamilyMember<PicNode>(
                     new PicNode("HetepheresII",
                        Properties.Resources.Hetepheres_II));
               FamilyMember<PicNode> DJEDEFRE =
                  new FamilyMember<PicNode>(
                     new PicNode("DJEDEFRE",
                        Properties.Resources.DJEDEFRE));
               FamilyMember<PicNode> Khentetka =
                  new FamilyMember<PicNode>(
                     new PicNode("Khentetka",
                        Properties.Resources.Khentetka));
               FamilyMember<PicNode> KHAFRE =
                  new FamilyMember<PicNode>(
                     new PicNode("KHAFRE",
                        Properties.Resources.KHAFRE));
               FamilyMember<PicNode> KhamerernebtyI =
                  new FamilyMember<PicNode>(
                     new PicNode("KhamerernebtyI",
                        Properties.Resources.Khamerernebty_I));
               FamilyMember<PicNode> Hemiunu =
                  new FamilyMember<PicNode>(
                     new PicNode("Hemiunu",
                        Properties.Resources.Hemiunu));

               FamilyMember<PicNode> MeresankhII =
                  new FamilyMember<PicNode>(
                     new PicNode("MeresankhII",
                        Properties.Resources.Meresankh_II));

               FamilyMember<PicNode> Setka =
                  new FamilyMember<PicNode>(
                     new PicNode("Setka",
                        Properties.Resources.Setka));
               FamilyMember<PicNode> Hernet =
                  new FamilyMember<PicNode>(
                     new PicNode("Hernet",
                        Properties.Resources.Hernet));
               FamilyMember<PicNode> MeresankhIII =
                  new FamilyMember<PicNode>(
                     new PicNode("MeresankhIII",
                        Properties.Resources.Meresankh_III));
               FamilyMember<PicNode> MENKAURA =
                  new FamilyMember<PicNode>(
                     new PicNode("MENKAURA",
                        Properties.Resources.MENKAURA));
               FamilyMember<PicNode> KhamerernebtyII =
                  new FamilyMember<PicNode>(
                     new PicNode("KhamerernebtyII",
                        Properties.Resources.Khamerernebty_II));

               FamilyMember<PicNode> Baka =
                  new FamilyMember<PicNode>(
                     new PicNode("Baka",
                        Properties.Resources.Baka));
               FamilyMember<PicNode> Neferhetepes =
                  new FamilyMember<PicNode>(
                     new PicNode("Neferhetepes",
                        Properties.Resources.Neferhetepes));

               FamilyMember<PicNode> SHEPSESKAF =
                  new FamilyMember<PicNode>(
                     new PicNode("SHEPSESKAF",
                        Properties.Resources.SHEPSESKAF));
               FamilyMember<PicNode> Bunefer =
                  new FamilyMember<PicNode>(
                     new PicNode("Bunefer",
                        Properties.Resources.Bunefer));

               FamilyMember<PicNode> Djedefptah =
                  new FamilyMember<PicNode>(
                     new PicNode("Djedefptah",
                        Properties.Resources.Djedefptah));
               FamilyMember<PicNode> Khamaat =
                  new FamilyMember<PicNode>(
                     new PicNode("Khamaat",
                        Properties.Resources.Khamaat));


               HetepheresI.Add(MerititesI);
               HetepheresI.Add(KHUFU);
               HetepheresI.Add(Henutsen);
               Unknown.Add(Rahotep);
               Unknown.Add(NefermaatI);
               Unknown.Add(Itet);
               MerititesI.Add(Djedefhor);
               MerititesI.Add(Kawab);
               KHUFU.Add(HetepheresII);
               KHUFU.Add(DJEDEFRE);
               KHUFU.Add(Khentetka);
               KHUFU.Add(KHAFRE);
               KHUFU.Add(KhamerernebtyI);
               NefermaatI.Add(Hemiunu);
               Djedefhor.Add(MeresankhII);
               DJEDEFRE.Add(Setka);
               DJEDEFRE.Add(Hernet);
               DJEDEFRE.Add(MeresankhIII);
               DJEDEFRE.Add(MENKAURA);
               DJEDEFRE.Add(KhamerernebtyII);
               Setka.Add(Baka);
               Setka.Add(Neferhetepes);
               MENKAURA.Add(SHEPSESKAF);
               MENKAURA.Add(Bunefer);
               SHEPSESKAF.Add(Djedefptah);
               SHEPSESKAF.Add(Khamaat);

               ShowTree();
            }

VB.NET

   Private Sub Form1_Load(ByVal sender As Object, _
         ByVal e As EventArgs)

      Dim MerititesI As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("MerititesI", _
         My.Resources.Meritites_I))
      Dim KHUFU As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("KHUFU", _
         My.Resources.KHUFU))
      Dim Henutsen As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("Henutsen", _
         My.Resources.Henutsen))
      Dim Rahotep As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("Rahotep", _
         My.Resources.Rahotep))
      Dim NefermaatI As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("NefermaatI", _
         My.Resources.Nefermaat_I))
      Dim Itet As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("Itet", _
         My.Resources.Itet))
      Dim Djedefhor As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("Djedefhor", _
         My.Resources.Djedefhor))
      Dim Kawab As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("Kawab", _
         My.Resources.Kawab))
      Dim HetepheresII As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("HetepheresII", _
         My.Resources.Hetepheres_II))
      Dim DJEDEFRE As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("DJEDEFRE", _
         My.Resources.DJEDEFRE))
      Dim Khentetka As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("Khentetka", _
         My.Resources.Khentetka))
      Dim KHAFRE As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("KHAFRE", _
         My.Resources.KHAFRE))
      Dim KhamerernebtyI As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("KhamerernebtyI", _
         My.Resources.Khamerernebty_I))
      Dim Hemiunu As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("Hemiunu", _
         My.Resources.Hemiunu))
      Dim MeresankhII As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("MeresankhII", _
         My.Resources.Meresankh_II))
      Dim Setka As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("Setka", _
         My.Resources.Setka))
      Dim Hernet As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("Hernet", _
         My.Resources.Hernet))
      Dim MeresankhIII As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("MeresankhIII", _
         My.Resources.Meresankh_III))
      Dim MENKAURA As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("MENKAURA", _
         My.Resources.MENKAURA))
      Dim KhamerernebtyII As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("KhamerernebtyII", _
         My.Resources.
      Dim Baka As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("Baka", _
         My.Resources.Baka))
      Dim Neferhetepes As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("Neferhetepes", _
         My.Resources.Neferhetepes))
      Dim SHEPSESKAF As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("SHEPSESKAF", _
         My.Resources.SHEPSESKAF))
      Dim Bunefer As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("Bunefer", _
         My.Resources.Bunefer))
      Dim Djedefptah As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("Djedefptah", _
         My.Resources.Djedefptah))
      Dim Khamaat As FamilyMember(Of PicNode) = New _
         FamilyMember(Of PicNode)(New PicNode("Khamaat", _
         My.Resources.Khamaat))

      HetepheresI.Add(MerititesI)
      HetepheresI.Add(KHUFU)
      HetepheresI.Add(Henutsen)
      Unknown.Add(Rahotep)
      Unknown.Add(
      Unknown.Add(Itet)
      MerititesI.Add(Djedefhor)
      MerititesI.Add(Kawab)
      KHUFU.Add(HetepheresII)
      KHUFU.Add(DJEDEFRE)
      KHUFU.Add(Khentetka)
      KHUFU.Add(KHAFRE)
      KHUFU.Add(KhamerernebtyI)
      NefermaatI.Add(Hemiunu)
      Djedefhor.Add(MeresankhII)
      DJEDEFRE.Add(Setka)
      DJEDEFRE.Add(Hernet)
      DJEDEFRE.Add(MeresankhIII)
      DJEDEFRE.Add(MENKAURA)
      DJEDEFRE.Add(KhamerernebtyII)
      Setka.Add(Baka)
      Setka.Add(Neferhetepes)
      MENKAURA.Add(SHEPSESKAF)
      MENKAURA.Add(Bunefer)
      SHEPSESKAF.Add(Djedefptah)
      SHEPSESKAF.Add(Khamaat)

      ShowTree()

   End Sub

Finish up.

C#

      private void picFamily_Paint(object sender, PaintEventArgs e)
      {

         e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
         e.Graphics.TextRenderingHint =
            TextRenderingHint.AntiAliasGridFit;

         Unknown.DrawFamily(e.Graphics);
         // HetepheresI.DrawFamily(e.Graphics);
         // SNEFERU.DrawFamily(e.Graphics);
      }


      private void picFamily_MouseClick(object sender,
         MouseEventArgs e)
      {

         SelNode(e.Location);

      }

VB.NET

   Private Sub picFamily_Paint(ByVal sender As Object, ByVal e _
         As PaintEventArgs)

      e.Graphics.SmoothingMode = SmoothingMode.AntiAlias
      e.Graphics.TextRenderingHint = _
         TextRenderingHint.AntiAliasGridFit

      Unknown.DrawFamily(e.Graphics)

      'HetepheresI.DrawFamily(e.Graphics)'
      'SNEFERU.DrawFamily(e.Graphics)'

   End Sub

   Private Sub picFamily_MouseClick(ByVal sender As Object, _
         ByVal e As MouseEventArgs)

      SelNode(e.Location)

   End Sub

When you run the program, you can get three different Trees. These trees are shown in Figures 2-4.

Hetepheres I
Figure 2: Hetepheres I

SNEFERU
Figure 3: SNEFERU

Unknown
Figure 4: Unknown

C# Source on GitHub

VB.NET Source on GitHub

Conclusion

There, see how easy it was to create family tree in .NET? I hope you have learnt a lot about programming today, and a bit of history as well.

Hannes DuPreez
Hannes DuPreez
Ockert J. du Preez is a passionate coder and always willing to learn. He has written hundreds of developer articles over the years detailing his programming quests and adventures. He has written the following books: Visual Studio 2019 In-Depth (BpB Publications) JavaScript for Gurus (BpB Publications) He was the Technical Editor for Professional C++, 5th Edition (Wiley) He was a Microsoft Most Valuable Professional for .NET (2008–2017).

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read