AlucardF0X
AlucardF0X

Reputation: 31

Issues with WinForms Form.Controls.Add

Microsoft Visual Studio 2010 Express Windows Forms C#


Horay, more issues with ControlCollections and Form.Controls.Add()!

        private void mainForm_Load(object sender, EventArgs e) {
        data.mainForm_startControls = this.Controls;
        data.wizard_tabs = new Wizard_Tabs().Controls[0];
        debug(1);
        this.Controls.Clear();
        debug(2);
     >  this.Controls.Add(data.mainForm_startControls[3]);
        debug(3);
        }

Why does the highlighted (with a >) line act as a "return;" statement in this snippet?

If it's executed, debug(3); doesn't run. I don't have the wisdom to solve this.

The line itself doesn't even execute. Removing it fixes all of it, so it's the problem!

If you were wondering what data. stands for:

namespace Project_Management_Wizard {
public class dataStorage {
    public System.Windows.Forms.Control.ControlCollection mainForm_startControls;
    public System.Windows.Forms.Control wizard_tabs;

    }
}


public dataStorage data = new dataStorage();

Something I didn't quite figure out at start is that the ControlCollection is just an array of references to the actual Controls. Copying it only makes a copy of references. I thought ControlCollection holds the actual elements, so I can copy the elements by copying the ControlCollection. Copying the ControlCollection doesn't copy any collections, so editing the collections it points to gives errors.

Upvotes: 0

Views: 821

Answers (3)

psubsee2003
psubsee2003

Reputation: 8751

Your problem is dealing with assignment by reference, when you think you are creating a copy.

When you assign data.mainForm_startControls = this.Controls; you are assigning a reference to this.Controls to data.mainForm_startControls. This is standard with dealing with any reference type in C#. You aren't copying the collection, you are just assigning it to a 2nd variable.

If you modify this.Controls, virtually any change will be reflected in data.mainForm_startControls. In fact, the only change I can think of at the moment that would not impact data.mainForm_startControls is if you actually created a brand new object and assigned it to this.Controls.

So when you call this.Controls.Clear(), you are clearing the ControlCollection object and since data.mainForm_startControls references the same object, you are clearing it as well.

What you need to do instead is assign the individual elements to a new collection rather than assigning the entire collection.

First, I'd suggest changing ControlCollection in dataStorage to a more modern collection, such as List<T>. Dealing with Generic collection classes in .NET is a lot easier since everything is strongly typed.

public class dataStorage {
    public List<Control> mainForm_startControls = new List<Control>()
    public System.Windows.Forms.Control wizard_tabs;

}

Then you can replace data.mainForm_startControls = this.Controls; with a foreach loop to copy the individual controls:

foreach (Control item in this.Controls)
{
    data.mainForm_startControls.Add(item);
}

So this way you have a brand new collection that will hold references to each of the controls, and it won't get cleared when you call this.Controls.Clear()

Upvotes: 1

Richard Arp&#225;š
Richard Arp&#225;š

Reputation: 51

I think the line you selected throws an exception and therefore the next line will not execute.

The reason for an exception is the fact, that data.mainForm_startControls[3] doesnt exist, because the collection is empty. You cleared it with this.Controls.Clear(). Because this.Controls and data.mainForm_startControls are the same pointers, the Clear method clears also data.mainForm_startControls.

Upvotes: 4

Grant Winney
Grant Winney

Reputation: 66509

Sounds like that line is throwing an exception. Try placing a try/catch block around it, then place a breakpoint in the catch and see if it is in fact throwing.

Things to check for:

  • Is mainForm_startControls instantiated?

  • Does mainForm_startControls actually have 4 elements in it, so that mainForm_startControls[3] will return a value?

Upvotes: 1

Related Questions