2010-04-11 13 views
10

¿Hay algún otro método de llevar un control al frente que no sea control.BringToFront()? Tengo una serie de etiquetas en un control de usuario y cuando trato de llevar una de ellas al frente, no funciona. Incluso hice un bucle en todos los controles y les envié todo el reverso excepto el que me interesa y no cambia nada.Llevar el control Winforms al frente

Aquí es el método en el que se añade una etiqueta para el control de usuario

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

Aquí es el método que envía todos ellos a la parte posterior.

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

Algún código de ejemplo sería bueno. ¿Estás seguro de que los controles están en el mismo control de contenedor? Establecer un control al frente solo lo convertirá en el control frontal en su contenedor. – Patrick

+0

Esta publicación me ayudó a resolver exactamente el mismo problema. – IbrarMumtaz

Respuesta

14

Sí, hay otra manera. El Controls.SetChildIndex() también cambia el orden Z. El que tiene el índice 0 es el que está en la parte superior. Sin embargo, no le compra nada, BringToFront() usa este método.

Su método SendLabelsToBack() dado no funciona, también enviará la etiqueta para agregar a la parte posterior. Pero su siguiente declaración corrige eso de nuevo.

Bien, eso no funciona, lo que significa que el método BringToFront() no se ejecuta. Busque en la ventana de Salida una notificación de "primera excepción de oportunidad". Tal como está escrito, su SendLabelsToBack() causará una excepción si el control del usuario contiene algún control que no sea UserLabel. Además, establezca un punto de interrupción después de la llamada BringToFront() y compruebe el valor de userContainer.Controls[0].Name cuando se rompe.

+0

Realmente no sigo esto la última porción porque el formulario solo se crea una instancia una vez. – Nathan

+0

Solo tratando de encontrar un motivo por el cual la etiqueta no sería visible. ¿Es de hecho visible pero posicionado mal? ¿O no es visible en absoluto? –

+0

Es visible detrás de otra etiqueta. – Nathan

3

El índice z de los controles es por contenedor.

Si llama a BringToFront en un control que está dentro de un contenedor (como un Panel), no traerá el contenedor al frente.
Por lo tanto, el control solo irá en frente de otros controles en ese contenedor.

Para ver en qué contenedores se encuentran sus controles, puede usar el panel del esquema del documento en el menú Ver.

EDIT: Su control userContainer está probablemente detrás de un control diferente.

4

¿Has probado Invalidate() después de BringToFront()? BringToFront no eleva el evento Paint

probar esto:

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

Lo intenté y tampoco ayudó. Parece que un par de etiquetas tienen el mismo índice Z y otras no. Desde mi punto de vista, todos deberían tener el mismo índice z si los configuro manualmente. – Nathan

+0

Esto no ayudará. – SLaks

+0

esta es una muy buena respuesta, funciona completamente ... –

2

Creo que sólo necesita cambiar su última línea:

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

a esto:

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

Cuando utiliza una cadena como indexador para la colección Controls, va por la propiedad Name de la estafa trol (no la propiedad FieldName).

Puesto que usted está tratando de lograr el control más recientemente añadidos a la parte superior, esto también funcionaría:

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

No; de lo contrario, obtendría una excepción. – SLaks

+0

@Slaks: según el uso en la pregunta, parece que 'FieldName' devolvería el mismo valor sin importar la instancia, como' FieldTop' y 'FieldLeft', etc. Así que' FieldName' podría ser el mismo nombre como primera instancia, por lo que la llamada a BringToFront siempre se aplica al primer control. – MusiGenesis

+0

¿Por qué no escribir simplemente 'field.BringToFront()'? Realmente no hay necesidad de encontrarlo en la colección de control cuando ya tiene una referencia. – Patrick

0

Desde mi experiencia se ve como Windows coloca todos los controles que pertenecen a un contenedor gráfico (panel, cuadro de grupo ... etc.) en una colección de software. La colección está ordenada por índice secundario, que es una propiedad de cada control en ese contenedor. El truco es que los niños con el mismo índice pueden y existen. En este caso, las ventanas pintarán a los niños ordenados en relación con otros, pero entre ellos los pintará en el orden inverso al que se agregaron al contenedor.

Resumen breve: para un contenedor, debe asegurarse de que los controles tengan índices diferentes al cambiar TODOS NO SÓLO ALGUNOS de los índices cuando desee cambiar el orden z. Por ejemplo:

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

donde indexLogic(newControl) es su método de cálculo del índice de control particular.

Cuestiones relacionadas