C#:如何交换两个winform控件的位置

C#:如何交换两个winform控件的位置,c#,winforms,collections,controls,C#,Winforms,Collections,Controls,假设你有两个控件,Alice和Bob,你想交换他们的位置。我的意思是,在互换之后: 如果他们生活在同一个ControlCollection,Alice的索引应该是Bob,反之亦然 如果在不同的ControlCollections中,Alice应该与Bob具有相同的索引,但在BobsControlCollection中,反之亦然 你会怎么做?我有点不确定如何最好地解决这个问题,因为ControlCollection方法是如何工作的。例如,使用Remove方法删除控件将更改集合中紧随其后的所有控

假设你有两个
控件,Alice和Bob,你想交换他们的位置。我的意思是,在互换之后:

  • 如果他们生活在同一个
    ControlCollection
    ,Alice的索引应该是Bob,反之亦然
  • 如果在不同的
    ControlCollection
    s中,Alice应该与Bob具有相同的索引,但在Bobs
    ControlCollection
    中,反之亦然
你会怎么做?我有点不确定如何最好地解决这个问题,因为
ControlCollection
方法是如何工作的。例如,使用
Remove
方法删除控件将更改集合中紧随其后的所有控件的索引。SetChildIndex的工作方式与此类似


编辑:Alice和Bob的父控件是流布局面板。这就是为什么我想交换它们的索引,这实际上会交换它们在流布局面板中的位置。

我认为您无法完全实现您想要实现的目标。但您的要求对我来说似乎很奇怪:您可以在一个表单中完全直观地交换两个控件,而不受父控件的
ControlCollection
中各自索引的任何约束

最接近的方法是将控件存储在
面板中:

  • 您将拥有
    PanelA
    PanelB
  • 首先,
    PanelA
    将包含
    Alice
    PanelB
    将包含
    Bob
  • 交换时,将
    Bob
    存储到
    PanelA
    中,将
    Alice
    存储到
    PanelB

Alice
Bob
不会直接出现在
ControlCollection
中,但只有
面板才会出现。

我认为您必须从正在使用的
ControlCollection
中删除所有控件,并将它们存储到尊重元素顺序的数据结构中(可能是
SortedList
?)

在第一种情况下,您需要在
SortedList
中交换Alice和Bob,然后将
SortedList
中的所有控件重新添加回
ControlCollection

第二种情况与第一种情况类似,只是您有2个
SortedList
s,并且您可以在它们之间交换Alice和Bob

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);

可能不是最短的方法,但应该有效…

对于两个控件位于同一个
FlowLayoutPanel
上的简单情况,请使用
控件上的方法

像这样的

var alphaIndex = panel.Controls.IndexOf(controlAlpha);
var betaIndex = panel.Controls.IndexOf(controlBeta);
panel.Controls.SetChildIndex(controlAlpha, betaIndex);
panel.Controls.SetChildIndex(controlBeta, alphaIndex);
注意:我在这里没有正确处理顺序-您需要首先将前面的控件放置到位,否则当第二个控件移到它前面时,结果索引将过高。但这是读者的练习


对于更复杂的情况,当控件位于不同的
FlowLayoutPanel
s上时,代码更简单(顺序没那么重要),也更复杂(每个控件都需要从一个面板中删除,然后添加到另一个面板中)。

我在研究这个问题时遇到了一些问题。 我发现
Control.BringToFront()
实际上改变了
ControlCollection
中的位置

因此:


将颠倒
控件集合中的顺序

对不起,应该说它们所在的面板是流布局面板。因此,我需要交换它们的索引以交换它们的视觉位置。编辑了我的问题=)每个容器控件上的
控件
属性不是一个简单的列表-它本身是一个单独的对象(control.ControlCollection-),它为移动对象提供了直接支持。如果你按照你建议的方式删除并重新添加所有控件,UI将闪烁一些可怕的东西——代码也会变慢。同意,但这会解决他的问题。我忘了可以用yopu回答的方式使用
SetChildIndex
,所以谢谢。:)
foreach(Control _control in this.Controls)
  _control.BringToFront()