3
votes

I have a place in my code where I am dynamically adding controls to a Top-Down arranged FlowLayoutPanel. I need the controls to appear in a certain order so what I am doing everytime is clearing the FlowLayoutPanel.Controls collection and then adding each child control in the order I want them to appear. My code does this:

private void arrangement1()
{
    flowLayoutPanel1.Controls.Clear();
    flowLayoutPanel1.Controls.Add(control1);
    flowLayoutPanel1.Controls.Add(control2);
    flowLayoutPanel1.Controls.Add(control3);
}

Most of the time this works great. However, there is one specific control that does not maintain it's position in the control collection when adding other controls after it. For instance in the following code segment:

private void arrangement2()
{
    flowLayoutPanel1.Controls.Clear();
    flowLayoutPanel1.Controls.Add(control1);
    flowLayoutPanel1.Controls.Add(movingControl);
    //movingControl current is at index = 1 in Controls.
    flowLayoutPanel1.Controls.Add(control2);
    //control2 is now at index = 1, movingControl got bumped to index = 2 in Controls.
    flowLayoutPanel1.Controls.Add(control3);
    //control3 is now at index =2, movingControl got bumped to index = 3 in Controls.
}

This only happens the first time movingControl is added to Controls. If I go back and call arrangement1 and then arrangement2 a second time. The controls will appear the in intended order of:

  • control1
  • movingControl
  • control2
  • control3

This seems to be a bug in the code for Controls.Add. Either that or the documentation for .Add's behaviour is incomplete as it doesn't always add to the end of the collection. Does anyone have any insight into why this occurs. The obvious "fix" is to just call:

arrangement2();
arrangement1();
arrangement2();

However, that seems like a very poor solution to some other underlying problem.

Thanks in advance for the help!

EDIT: Note that each of these controls is a member of a custom view class so they persist after the Controls collection is Cleared. However, these controls are not stored in any sort of ordered collection. They are just members of this custom class. The code shown above works correctly as shown. However, in the context of my GUI program it has the described erroneous behaviour. I would post more code if I had any idea what would be helpful but there is a lot of code that touches these peices. This is all of the code that executes for the described action.

What I'm really looking for is what possible scenarios cause a Controls.Add to Insert a control not at the last index of the collection. Specifically after a call to Clear() and with NO Remove() calls.

2
Had a somewhat similar issue - Instead of using Controls.Add(button) I was using Button.parent = flowLayoutPanel. Doing this caused the order to change - switching to controls.add put everything in the right order. - John M

2 Answers

1
votes

First running Arrangement1 gives me: control1 control2 control3

Running arrangement2 gives me: control1 movingcontrol control2 control3

Your code, pure as it is posted, works for me.

However, recently i encountered a similar problem. I was holding the controls in a list, then itterating through this to add them to the flowlayout. Removing a single item from the list, then adding a new control would not insert the new control at the end, it would replace the vacant spot left by the deleted item.

So in summary, i suspect it's something you haven't posted, possibly where you store the controls themselves? do you store them in an array or a List?

0
votes

Would it not be easier to just toggle the visibilty of movingControl?

But I guess that answer is based on your example such that if more rearranging is going on then this may not apply.

In conjunction with visibility toggling, you could also look into using ControlCollection.SetChildIndex() instead which seems more appropriate and seems more likely to produce a smoother re-ordering.