2
votes

I'm working on a legacy project, which has been developed over the course of a number of years. The structure is very object-orientated meaning that there are multiple levels of inheritance on the forms. This particular set of forms I am working on has 7-levels from the base form, all the way up to the derived form I need to change (at each level the inherited forms can be inherited further by other forms, but that's outside of the scope of my work thankfully). The inheritance therefore looks something like this:

Base Form
Derived Form 1 : Base Form
Derived Form 2 : Derived Form 1
...
Derived Form 7 : Derived Form 6

The problem I have is that I am doing some UI refactoring, which involves ensuring certain control types are of the correct size/location/padding etc, but the original base form has a lot of controls in, not all of which are used in the derived forms. What seems to be happening is that there will be, for example the following:

MyBasePanel

MyBaseGroupBox

MyBaseTextBox1

The above would be defined in the base form, but as an example Derived Form 5 might add controls to MyBaseGroupBox, which I need to refactor. I am using the Document Outline feature in VS2013 to view the hierarchy, but it is a real pain to spot small changes between forms. My question therefore, is there a way that I can easily see which controls have been defined ONLY on the derived form and don't exist on the base form?

I also have an issue that controls seem to be created in the derived form and then are either hidden or put behind controls derived in a previous form, which makes it even more annoying.

1
Does this need to be done to provide a list in code or are you just looking at a way to get a list for yourself containing the controls?Sayse
Just an easy way of seeing the differences between the forms. At present I'm using the doc outline to inspect each panel/group box in turn to see what controls have been added so that I can refactor them.Andrew
You could do a simple linq query where you create an instance of Form6 and Form7 and then just do form7.Controls.Where(c => !form6.Controls.Contains(c));?Sayse
Yeah that's a possibility thanks. Most of the forms aren't designed to be explicitly displayed, i.e. they are only used as the base for other forms, but I could probably write a wrapper project to show them.Andrew
If they aren't designed to be shown then I would imagine they have no new controls? just look for the level where it is shown and compare with that (Note: It doesn't need to be shown, just initialized)Sayse

1 Answers

0
votes

You could use reflection, and then invoke the GetValue FieldInfo or PropertyInfo to determine which class the control was declared in, and then color it appropriately. The disadvantage is that it wouldn't be able to detect controls added anonymously.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;

namespace SimpleForm {

public class FormA : Form {

    Button btn1 = new Button { Text = "Button1" };

    public FormA() {
        Controls.Add(btn1);

        Button btn1a = new Button { Text = "Button1a" }; // not colored
        btn1a.Location = new Point(0, 50);
        Controls.Add(btn1a);
    }
}

public class FormB : FormA {

    Button btn2 = new Button { Text = "Button2" };

    public FormB() {
        btn2.Location = new Point(0, 100);
        Controls.Add(btn2);
        btn2.Click += delegate {
            ColorIt.ColorControls(this);
        };
    }
}

public static class ColorIt {

    private static void GetAllControls(Control c, List<Control> list) {
        // only pick controls that have no children (e.g. button, textbox, etc)
        if (c.Controls.Count == 0)
            list.Add(c);
        else
            foreach (Control c2 in c.Controls)
                GetAllControls(c2, list);
    }

    public static void ColorControls(Control parent) {

        Type[] fs = new [] { typeof(FormA), typeof(FormB) };
        Color[] colors = new [] { Color.Red, Color.Blue };
        List<Control> controls = new List<Control>();
        GetAllControls(parent, controls);

        foreach (Control c in controls) {
            Type t = c.GetType();
            for (int i = 0; i < fs.Length; i++) {
                Type f = fs[i];
                Color clr = colors[i];

                foreach (var pi in f.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) {
                    if (pi.PropertyType == t && pi.GetValue(parent) == c) {
                        c.ForeColor = clr;
                        c.BackColor = clr;
                    }
                }
                foreach (var fi in f.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) {
                    if (fi.FieldType == t && fi.GetValue(parent) == c) {
                        c.ForeColor = clr;
                        c.BackColor = clr;
                    }
                }
            }
        }
    }
}