A: 

I don't think you can do exactly what you are trying to achieve. But your requirements seem strange to me : you can perfectly visually swap two controls in a form without any constraint on their respective index in their parent's ControlCollection.

The closest you could get would be to store your controls in a Panel :

  • You'd have PanelA and PanelB.
  • At first, PanelA would contain Alice and PanelB would contain Bob.
  • When swapping, store Bob into PanelA and Alice into PanelB.

Alice and Bob would not appear directly in the ControlCollection though, only the Panels would.

Mac
Sorry, should have said that the panels they are in are flow layout panels. So that is why I need to swap their index to swap their visual position. Edited my question =)
Svish
A: 

I'd say you have to remove all controls from the ControlCollection(s) you're working with and store them into a data structure(s) that respects the order of elements (maybe a SortedList?).

In the first case, you'd then swap Alice and Bob in the SortedList and then re-add all the controls from the SortedList back into the ControlCollection.

The second case would be similar to the first except that you'd have 2 SortedLists, and you'd swap Alice and Bob between them.

Ian Kemp
The `Controls` property present on every container control isn't a simple list - it's a separate object in it's own right (Control.ControlCollection - http://msdn.microsoft.com/en-us/library/system.windows.forms.control.controlcollection(VS.71).aspx) and it provides direct support for moving things around. If you remove and re-add all the controls in the way you suggest, the UI will flicker something terrible - and the code will be **slow**.
Bevan
Agreed, but it would solve his problem. I forgot that it's possible to use `SetChildIndex` in the way yopu answered, so thanks for that. :)
Ian Kemp
A: 
Control bobParent = bob.Parent;
Control aliceParent = alice.Parent;
int bobIndex = bobParent.Controls.GetChildIndex(bob);
int aliceIndex = aliceParent.Controls.GetChildIndex(alice);
bobParent.Controls.Add(alice);
aliceParent.Controls.Add(bob);
bobParent.Controls.SetChildIndex(alice, bobIndex);
aliceParent.Controls.SetChildIndex(bob, aliceIndex);

Probably not the shortest way, but it should work...

Thomas Levesque
A: 

For the simple case, where both controls are on the same FlowLayoutPanel, use the SetChildIndex method on Controls.

Something like this ...

var alphaIndex = panel.Controls.IndexOf(controlAlpha);
var betaIndex = panel.Controls.IndexOf(controlBeta);
panel.Controls.SetChildIndex(controlAlpha, betaIndex);
panel.Controls.SetChildIndex(controlBeta, alphaIndex);

Note: I haven't handled sequence here properly - you need to put the earlier control into place first, else when the second is moved ahead of it, the resulting index will be one too high. But that's an exercise for the reader.

For the more complex case, where the controls are on different FlowLayoutPanels, the code is simpler (sequence doesn't matter so much) and more complicated (each control needs to be removed from one panel and added to the other).

Bevan