2010-04-11 74 views
10

除了control.BringToFront()之外,是否还有其他方法将控件带到前端?我在用户控件上有一系列标签,当我尝试将其中一个标签带到前面时,它不起作用。我甚至通过所有的控制,并把它们全部发回,除了我感兴趣的那个,它不会改变一件事。将Winforms控件带到前面

这里是一个标签被添加到用户控制

private void AddUserLabel() 
{ 
    UserLabel field = new UserLabel(); 
    ++fieldNumber; 

    field.Name = "field" + fieldNumber.ToString();   

    field.Top = field.FieldTop + fieldNumber; 
    field.Left = field.FieldLeft + fieldNumber; 
    field.Height = field.FieldHeight; 
    field.Width = field.FieldWidth; 
    field.RotationAngle = field.FieldRotation; 
    field.Barcode = field.BarCoded; 
    field.HumanReadable = field.HumanReadable; 
    field.Text = field.FieldText; 
    field.ForeColor = Color.Black; 

    field.MouseDown += new MouseEventHandler(label_MouseDown); 
    field.MouseUp += new MouseEventHandler(label_MouseUp); 
    field.MouseMove += new MouseEventHandler(label_MouseMove); 

    userContainer.Controls.Add(field); 

    SendLabelsToBack(); //Send All labels to back 

    userContainer.Controls[field.FieldName].BringToFront(); 
} 

方法下面是发送所有这些在后的方法。

private void SendLabelsToBack() 
{ 
    foreach (UserLabel lbl in userContainer.Controls) 
    { 
     lbl.SendToBack(); 
    } 
} 
+0

一些示例代码会很好。你确定控件在同一个容器控件中吗?将控件设置为前面只会使其成为其容器中的前端控件。 – Patrick 2010-04-11 18:05:20

+0

这篇文章帮助我解决了完全相同的问题。 – IbrarMumtaz 2011-12-26 15:20:05

回答

14

呀,还有另一种方式。 Controls.SetChildIndex()也改变Z顺序。索引0的那个是最上面的那个。尽管如此,你不会购买任何东西,BringToFront()使用这种方法。

您的SendLabelsToBack()方法因为无法正常工作,它也会将标签发送到后面添加。但是你的下一个陈述再次修复了这一点。

好的,这不起作用,这意味着BringToFront()方法不会被执行。在输出窗口中查找“第一次机会异常”通知。如书面所述,如果用户控件包含UserLabel以外的任何控件,则您的SendLabelsToBack()将导致异常。此外,在BringToFront()调用之后设置断点,并在断开时检查值userContainer.Controls[0].Name

+0

因为表单只有一次实例化,所以我并不真正关注这个最后部分。 – Nathan 2010-04-11 18:53:03

+0

试图想出一个标签不可见的原因。它实际上是可见的,但定位错误?还是根本看不到? – 2010-04-11 18:57:26

+0

它在另一个标签后面可见。 – Nathan 2010-04-11 18:58:54

3

控件的z索引是每个容器。

如果您在容器内的控件(例如Panel)上调用BringToFront,它不会将容器放在前面。
因此,该控件只会在该容器中的其他控件前面出现。

要查看控件所在的容器,可以使用“视图”菜单中的“文档大纲”窗格。

编辑:您的userContainer控制可能落后于不同的控制。

4

你试过Invalidate()BringToFront()? BringToFront不会引发Paint事件

试试这个:

private void SendLabelsToBack() 
{ 
    foreach (UserLabel lbl in userContainer.Controls) 
    { 
     lbl.SendToBack(); 
     lbl.Invalidate(); 
    } 
} 
+0

我刚刚尝试过,也没有帮助。它看起来像一对夫妇标签具有相同的Z指数,有些则没有。根据我的理解,如果我手动设置它们,它们应该都具有相同的z-index。 – Nathan 2010-04-11 18:31:57

+0

这不会帮助。 – SLaks 2010-04-11 18:33:03

+0

这是非常好的答案,完全有效... – 2014-10-11 05:52:32

2

我想你只需要改变你的最后一行:

userContainer.Controls[field.FieldName].BringToFront(); 

这样:

userContainer.Controls[field.Name].BringToFront(); 

当你使用一个字符串作为控件集合的索引器,它通过控制器的Name属性trol(不属于FieldName属性)。

既然你只是试图把最近添加的控制上,这也将工作:

userContainer.Controls[userContainer.Controls.Count - 1].BringToFront(); 
+0

不;否则,他会得到一个例外。 – SLaks 2010-04-11 18:33:23

+0

@Slaks:基于问题中的用法,无论“FieldTop”和“FieldLeft”等实例如何,“FieldName”都会返回相同的值。因此,“FieldName”可能恰好是相同的名称作为第一个实例,因此对BringToFront的调用始终应用于第一个控件。 – MusiGenesis 2010-04-11 18:37:14

+0

为什么不直接键入'field.BringToFront()'?当他已经有一个引用它时,真的不需要在控件集合中找到它。 – Patrick 2010-04-11 18:42:32

0

根据我的经验,Windows将属于一个图形容器(窗格,组框等)的所有控件放入软件集合中。该集合按子容器排序,子容器是该容器中每个控件的属性。 诀窍是具有相同索引的孩子可以并且确实存在。在这种情况下,窗口会绘制相对于其他人订购的那些孩子,但在他们之间,它们将以与他们添加到容器中相反的顺序绘制它们。

长话短说:对于一个容器,当需要更改z顺序时,您需要通过更改所有不只是某些索引来确保控件具有不同的索引。例如:

foreach (Control newControl in TopControl.Controls) 
{ 
    TopControl.Controls.SetChildIndex(newControl,indexlogic(newControl)); 
} 

其中indexLogic(newControl)是您计算特定控制指数的方法。