Create Form Controls based on the properties of a class Is there a better way to create Form Controls for properties of a class? Right now, I iterate through all properties of a class and have a method to create the Form Control for that property based on the type of the property.

private void AddControl(PropertyInfo p, string name = null, Color? c = null, int count = 0)
{
    Label newLabel = new Label();
    TableLayoutPanel tp = new TableLayoutPanel();
    Control ctrl = new Control();

    tp.ColumnCount = 2;
    tp.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 200F));
    tp.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 215F));
    tp.Margin = new Padding(0);
    tp.Name = "tp";
    tp.RowCount = 1;
    tp.RowStyles.Add(new RowStyle(SizeType.Absolute, 28F));
    tp.Size = new System.Drawing.Size(380, 28);
    tp.Location = new Point(0, 14 + num * 28);

    newLabel.Name = "lbl_" + num; 
    newLabel.Text = GetPropertyAttributes(p); // gets a custom attributes for the property
    newLabel.AutoSize = true;
    newLabel.Anchor = AnchorStyles.Left;

    tp.Controls.Add(newLabel);
    ToolTip myToolTip = new ToolTip();

    switch (p.PropertyType.Name)
    {
        case "String":
            ctrl = new TextBox();
            ctrl.Tag = "String";
            ctrl.Size = new System.Drawing.Size(170, 20);
            goto case "common";
        case "Boolean":
            ctrl = new CheckBox();
            goto case "common";
        case "Array[]":
            Console.WriteLine("Array");
            break;
        case "Int32":
            ctrl = new TextBox();
            ctrl.Tag = "Int";
            ctrl.Size = new System.Drawing.Size(40, 20);
            goto case "common";
        case "Double":
            ctrl = new TextBox();
            ctrl.Tag = "Double";
            ctrl.Size = new System.Drawing.Size(40, 20);
            goto case "common";
        case "IList`1":
            if (ClassExists(p.Name)) // ClassExists checks if the property is a class itself
            {
                ctrl = new Button();
                ctrl.Text = "Add";
                ctrl.Tag = p;
                ctrl.AutoSize = true;
                ctrl.Click += new EventHandler(AddButton_Click);
            }
            else
            {
                // TODO create gridview 
            }
            goto case "common";
        case "common":
            ctrl.Anchor = AnchorStyles.Left;
            ctrl.Name = name ?? GetPropertyAttributes(p);
            ctrl.Font = new Font("Consolas", 9);
            ctrl.KeyPress += new KeyPressEventHandler(textBoxKeyPress);
            if (c != null)
            {
                tp.BackColor = c ?? Color.Black;
            }
            tp.Controls.Add(ctrl);
            formControls.Add(tp); // List&lt;Control&gt;
            break;
        default:
            ctrl = new Button();
            ctrl.Text = "Add";
            ctrl.Tag = p;
            ctrl.AutoSize = true;
            ctrl.Click += new EventHandler(AddButton_Click);
            goto case "common";
    }
}

private void AddControls()
{
    foreach (Control ctrl in formControls)
    {
        MainPanel.Controls.Add(ctrl); // MainPanel is a Panel Control
    }
}


Can it be simplified? I may have to add more types to it.
In my commented I suggested a class that could do what you want it to do out of the box. However sometimes having a custom piece of code to show things in a better way is the goal. I can see this going in two different ways. One is to use a variation of the Visitor pattern and a list, and the other is to use a dictionary with Type and the key, and the class that represents how to view it as the value.

The first way you could make the IVisitor interface one of two ways.

public interface IVisotor
{
    //option 1
    void Accept(Control control);
    //option 2
    bool Accept(Control control);
}


then to implement you'd make a new class per type that you want to show a specific way. Here is an example with both.

public class StringVisitor : IVisitor
{
    public bool Accept(PropertyInfo property, Control control)
    {
        if(property.PropertyType != typeof(string))
            return false;

        Accept(control);
        return true;
    }

    public void Accept(Control control)
    {
        control = new TextBox();
        control.Tag = "String";
        control.Size = new System.Drawing.Size(170, 20);
    }
}


Now in your class you have two options, make a List&lt;IVisitor&gt; or make a Dictionary&lt;Type, IVisitor&gt;. Here is an example of what I mean. It is by no means complete (and might even have a compiler error as I did it in Notepad++)

public class PropertyViewer
{
    private readonly List&lt;IVisitor&gt; visitors1;
    private readonly Dictionary&lt;Type, IVisitor&gt; visitors2;

    public PropertyViewer()
    {
        visitors1 = new List
        {
            new StringVisitor(),
            //...
        };

        visitors2 = new Dictionary&lt;Type, IVisitor&gt;()
        {
            {String, new StringVisitor()},
            //...
        }
    }
    private void AddControl(PropertyInfo p, string name = null, Color? c = null, int count = 0)
    {
        Control control = null;
        //option 1
        foreach(var visitor in visitors1)
        {
            if(visitor.Accept(p, control))
                break;
        }
        //option 20
        if(visitors2.ContainsKey(p.PropertyType))
        {
            visitors2[p.PropertyType].Accept(control);
        }

        //do your common control stuff here.
    }
}


There are other ways as well but that should encapsulate your work some and make it easier to find where a mistake is. Because of the nature of your work on this it won't be super easy to test that everything is visually pleasing, but the code should be encapsulated enough to make it easy to adjust what you need adjusted.