The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Panels in .NET

I'm teaching myself C#, but need more information on .NET's mysterious panels.  Specifically, when I do foreach on a particular panel's controls, I get an ordered list of the contained labels.  But when I try to reference the labels directly by index (ie, myPanel.Controls[index]), the results are unpredictable.  I'm guessing this an intentional design characteristic of container classes, but I don't know where to start learning about it.

I'm sorry to ask such novice question here, but msdn was not much help with this concept (perhaps I am searching for the wrong concept?).  I really just need a place to start looking for info; I will gladly do the required reading. Of course, please let me know if I'm way off base in my approach because that would be helpful too. :)

Also, any recommendations for sources of "real" .NET programming topics beyond intro/textbook material are greatly appreciated.

Thank you.
New grad Send private email
Wednesday, December 14, 2005
You shouldn't rely on the order of the controls in a container. Use the index only when you process all the controls and the order doesn't matter. If order is important (or you only need specific controls) use the name.
Why do you think panels are "mysterious"? You'll like them a lot after you'll "get it".
smalltalk Send private email
Wednesday, December 14, 2005
I agree, once you 'get it', panels will make sense.

As an aside, by trying to use the index, you're tying your code to a particular internal state of myPanel.  myPanel.Controls is a handy reference to get at the controls, but good practice says we shouldn't write code that depends on other objects' internal state.

[disclaimer: my experience with panels comes mostly from Java, using Panel & JPanel.  I too am learning C#.]

For example, say you have a control named 'foo' on myPanel.  If you move it or add another control to your panel, who's to say that 'foo' will stay in the same place in the control array?  myPanel.Controls[index_of_foo] may refer to 'foo' or something else.  Likewise if you remove 'foo' - code written to go after myPanel.Controls[index_of_foo] will still try to execute, but code written to go after 'foo' itself won't do the Wrong Thing.
a former big-fiver Send private email
Wednesday, December 14, 2005
When using a 'foreach' loop you can access the controls directly at that point:

foreach (Control thisControl in myPanel.Controls)
  if (thisControl is TextBox)
    (TextBox)thisControl.Text = "New text";

Given that you can access the properties/methods of the control and it's subcontrols, and given that in most cases the number of controls is relatively tiny and hence fast to loop through, why would you need indexed access?

In answer to your question regarding good sites I generally just use Google with a search string like:
  "c#" object type get controls foreach

In most cases, for virtually any topic, sample code can be found from the links on the first page or two. Usually I can get answers this way whilst other developers are still discussing the question.

If you'd still rather go directly to a site, then the one that provides the largest set of sample code from the Google results tends to be - just use the search option at the top.
Karl Cartlidge Send private email
Wednesday, December 14, 2005
Thank you all.  I do use the code project as a reference, and of course, I often Google for code.  However, I don't often get good conceptual explanations through Google.

  The only reason why I was trying to use an index with the Controls container was because in my little application, I know its position, but I don't necessarily know its name.

  Basically, I have a panel which will make various labels visible as they are needed.  I really would like to do something like

  (Label)("lbl" + currentvar).Visible = True

  but I'm having to rely on its position instead. It seems that I have to do this often. (My Perl background is showing itself!)  How do you solve this situation?

  I just got my hands on _Starting_Out_With_C#_ by Chegwidden & Gaddis, which is a textbook.  Any other C# or .NET books that you guys would recommend?

  Thank you.
New Grad Send private email
Wednesday, December 14, 2005
Are these Windows Forms (gui app) Panels or ASP.NET (web) Panels?

Actually, there's not a whole lot of difference in this case.

The thing is that you can't really depend on the order of controls remaining the same over time without a lot of extra care on your part. It's not worth it, especially when there's a better way.

I'm going to assume winforms here, but it's pretty much the same for

When you drag a control onto the designer, it creates a variable in your class; label1, label2, label3, and so on. (In general, you want to rename these variables to something useful.)

Each one of these variables deals with the control directly. So you can, for example, just say:

  label1.Visible = true;

and that's all you need to do. You do not need to go through the container.

If you need to deal with sets of controls, the easiest thing to do is create an array and stick them in. Something along these lines:

  // Place this in the constructor AFTER the call to InitializeComponents
  Control[] importantControls = new Control[] { label1, label2, label3, label4 };

Now you can say:

  importantControls[3].Visible = false;

and it works regardless of where things land in the container.
Chris Tavares Send private email
Wednesday, December 14, 2005
So you need the *position* not the *index*. Ok, now it makes sense. Just use a foreach and for every label check its position.
smalltalk Send private email
Wednesday, December 14, 2005
Another option is that if you can generate it's name, then you can use the FindControl method of Panel (it's actually a method on everything that inherits from Control).  So, you could do something like this:

    string name = "lbl" + var;

    Control control = myPanel.FindControl(name);

    control.Visible = true;

I can't talk to how performant this solution would be, as compared to accessing it by index.  However, I think this would be faster as it doesn't require casting each control to test whether or not it is a label.
Eric Marthinsen Send private email
Tuesday, December 20, 2005
A technique I use pretty regularly:

On form startup, iterate though your controls, and put them into a hashtable. Use the name as the index, and put the CONTROL ITSELF as the referenced object.

Later on, you can search for the name of the control in the hashtable, and return a reference to the control itself.
Brad Corbin Send private email
Wednesday, December 21, 2005

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
Powered by FogBugz