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

5
假设您有两个控件Alice和Bob,并且您想要交换它们的位置。我的意思是,在交换后:
  • 如果它们位于同一个ControlCollection中,则Alice应具有Bob的索引,反之亦然。
  • 如果在不同的ControlCollection中,则Alice应具有与Bob相同的索引,但位于Bob的ControlCollection中,反之亦然。
您会如何做到这一点?我有点不确定如何最好解决这个问题,因为ControlCollection方法的工作方式。例如,使用Remove方法删除控件将更改集合中其后面所有控件的索引。SetChildIndex也以类似的方式工作。
编辑:Alice和Bob的父控件是流式布局面板。这就是为什么我想交换它们的索引,从而实际上交换它们在流式布局面板中的位置。
5个回答

8

对于简单的情况,其中两个控件在同一个 FlowLayoutPanel 上,可以使用 Controls 上的 SetChildIndex 方法。

像这样...

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

注意:我没有正确处理这里的序列,您需要先放置早期控件,否则当第二个移动到它之前时,结果索引将会高一个。但这是给读者的练习。
对于更复杂的情况,其中控件位于不同的 FlowLayoutPanel 上,代码会更简单(序列并不那么重要),但更加复杂(每个控件需要从一个面板中删除并添加到另一个面板中)。

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

可能不是最短的方法,但应该能够正常工作...

0
我在研究这个问题时偶然发现了一些东西。我发现Control.BringToFront()实际上会改变ControlCollection中的位置。
所以:
foreach(Control _control in this.Controls)
  _control.BringToFront()

将会反转ControlCollection中的顺序。


0

我认为你无法完全实现你想要达到的目标。但是你的要求对我来说似乎很奇怪:你可以在表单中完美地交换两个控件,而不受它们在父级ControlCollection中的索引的任何限制。

你能做到的最接近的方法是将你的控件存储在一个Panel中:

  • 你会有PanelAPanelB
  • 起初,PanelA将包含Alice,而PanelB将包含Bob
  • 当交换时,将Bob存储到PanelA中,将Alice存储到PanelB中。

AliceBob不会直接出现在ControlCollection中,只会出现在Panel中。


抱歉,我应该说一下它们所在的面板是流式布局面板。因此,我需要交换它们的索引以交换它们的可视位置。已编辑我的问题 =) - Svish

-1

我建议你从你正在处理的ControlCollection(们)中移除所有控件,并将它们存储到一个能够保持元素顺序的数据结构中(也许是SortedList?)。

在第一种情况下,你会在SortedList中交换Alice和Bob的位置,然后将SortedList中的所有控件重新添加回ControlCollection中。

第二种情况与第一种类似,只是你会有两个SortedList,并且你需要在它们之间交换Alice和Bob。


2
每个容器控件上都存在的“控件”属性不是一个简单的列表——它本身是一个独立的对象(Control.ControlCollection - http://msdn.microsoft.com/en-us/library/system.windows.forms.control.controlcollection(VS.71).aspx),并且它直接提供移动元素的支持。如果您按照您建议的方式删除并重新添加所有控件,用户界面将会闪烁得非常厉害,代码也会变得**缓慢**。 - Bevan
同意,但这将解决他的问题。我忘记了可以按照你回答的方式使用SetChildIndex,所以谢谢你。 :) - Ian Kemp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接