¿Cómo obtener controles en WPF para llenar el espacio disponible?

304

Algunos controles WPF (como el Button) parecen consumir felizmente todo el espacio disponible en su contenedor si no especifica la altura que debe tener.

Y algunos, como los que necesito usar en este momento, el (multilínea) TextBoxy los ListBoxmás preocupados por tomar el espacio necesario para adaptarse a sus contenidos, y nada más.

Si coloca a estos tipos en una celda en un UniformGrid, se expandirán para adaptarse al espacio disponible. Sin embargo, las UniformGridinstancias no son adecuadas para todas las situaciones. ¿Qué sucede si tiene una cuadrícula con algunas filas establecidas en * altura para dividir la altura entre sí y otras * filas? ¿Qué sucede si tiene una StackPanely tiene una Label, una Listy una Button, cómo puede obtener la lista para ocupar todo el espacio que no se come en la etiqueta y el botón?

Creo que esto realmente sería un requisito de diseño básico, pero no puedo entender cómo hacer que llenen el espacio que podrían (ponerlos en DockPanely configurarlo para llenar tampoco funciona, parece, ya que el DockPanelsolo ocupa el espacio que necesitan sus 'subcontroles').

Una interfaz gráfica de usuario de tamaño variable sería bastante horrible si había que jugar con Height, Width, MinHeight, MinWidthetc.

¿Puedes vincular tus Heighty Widthpropiedades a la celda de la cuadrícula que ocupas? ¿O hay otra manera de hacer esto?

Runa Jacobsen
fuente
1
UniformGrid es increíble, mi nueva etiqueta de goto predeterminada. Me gustó la simplicidad de Stackpanels (me recuerda a un div) pero Uniform Grid hace exactamente lo que necesito.
Terrance
Re UniformGrid. El énfasis está en Uniforme. Parece que no puede ajustar el ancho de columna sin altura de fila. Solo es adecuado si cada pieza de contenido es del mismo tamaño. Reemplacé mi StackPanel con un Grid, y Stretch luego funcionó como esperaba.
pdschuller
Este artículo me ayudó a estirar cuadros de texto.
jpaugh

Respuestas:

162

Cada control derivado de Panelimplementa una lógica de diseño distinta realizada en Measure()y Arrange():

  • Measure() determina el tamaño del panel y cada uno de sus elementos secundarios
  • Arrange() determina el rectángulo donde se representa cada control

El último hijo de la DockPanelllena el espacio restante. Puede deshabilitar este comportamiento estableciendo la LastChildpropiedad en false.

La StackPanelpregunta a cada niño por su tamaño deseado y luego las pilas. El panel de pila llama Measure()a cada niño, con un tamaño disponible Infinityy luego usa el tamaño deseado del niño.

A Gridocupa todo el espacio disponible, sin embargo, establecerá a cada niño en su tamaño deseado y luego los centrará en la celda.

Puede implementar su propia lógica de diseño derivando de Panely luego anulando MeasureOverride()y ArrangeOverride().

Vea este artículo para un ejemplo simple.

usuario3837
fuente
8
El enlace ahora está muerto
usuario3690202
66
@ user3690202 Archive.org es tu amigo. Enlace reanimado.
ruffin
44
El tema todavía existe en MSDN, pero el enlace cambió a este: docs.microsoft.com/en-us/dotnet/framework/wpf/controls/…
Andrea Antonangeli
2
The last child of the DockPanel fills the remaining space: esta fue la clave que faltaba a mi entender. Siempre pensé que el elemento sin Dock explícito llenaba el espacio.
Visto el
238

También hay algunas propiedades que puede configurar para forzar a un control a llenar su espacio disponible cuando de otro modo no lo haría. Por ejemplo, puedes decir:

HorizontalContentAlignment="Stretch"

... para forzar que el contenido de un control se estire horizontalmente. O puedes decir:

HorizontalAlignment="Stretch"

... para forzar el control mismo a estirarse horizontalmente para llenar su padre.

Matt Hamilton
fuente
88
El panel más notorio mencionado en todos estos casos es el StackPanel. No contiene propiedades de ContentAlignment y establecer sus hijos en Stretch no tendrá ningún efecto dentro de una cuadrícula del tamaño de una estrella. Muy frustrante. Es casi como si el StackPanel fuera el primer contenedor que escribió el equipo de WPF y sufre por ese ser el caso.
Brent Schooley
44
@Brent - ¡ahh! He estado atascado en tratar de que el contenido de mi stackpanel se llene correctamente. ¡Gracias! Pensé que era algo que estaba haciendo muy mal.
Ashley Grenon
8
@townsean Stack panel es muy limitado, puede obtener un comportamiento similar al estirar con UniformGrid y establecer Filas o Columnas en 0
ForbesLindesay
2
@ Tuskan360 UniformGrid solo permite que las celdas tengan el mismo tamaño. Usé una cuadrícula al final, parece funcionar. Molesto cómo StackPanel no hace lo que aparentemente está diseñado para.
TarkaDaal
44
@TarkaDaal yeh, UniformGrid si todo tiene el mismo tamaño, Grid si desea especificar tamaños relativos complejos, apile el panel a solo el tamaño en función del contenido e ignore cuánto espacio está disponible.
ForbesLindesay
18

Bueno, lo descubrí yo mismo, justo después de publicar, que es la forma más vergonzosa. :)

Parece que cada miembro de un StackPanel simplemente llenará el tamaño mínimo requerido.

En el DockPanel, había acoplado las cosas en el orden incorrecto. Si TextBox o ListBox es el único elemento acoplado sin una alineación, o si son los últimos agregados, llenarán el espacio restante según lo deseado.

Me encantaría ver un método más elegante para manejar esto, pero servirá.

Runa Jacobsen
fuente
Solo quiero señalar (¡en esta vieja pregunta!) Que "sin una alineación" es una frase clave aquí, al menos lo fue para mí.
MikeBaz - MSFT
4

Utilice las propiedades de diseño HorizontalAlignment y VerticalAlignment . Controlan cómo un elemento usa el espacio que tiene dentro de su elemento primario cuando hay más espacio disponible del requerido por el elemento.

El ancho de un StackPanel, por ejemplo, será tan ancho como el elemento más ancho que contiene. Por lo tanto, todos los elementos más estrechos tienen un poco de espacio en exceso. Las propiedades de alineación controlan lo que hace el elemento hijo con el espacio extra.

El valor predeterminado para ambas propiedades es Estirar, por lo que el elemento hijo se estira para llenar todo el espacio disponible. Las opciones adicionales incluyen Izquierda, Centro y Derecha para Alineación Horizontal y Superior, Centro e Inferior para Alineación Vertical .

urini
fuente
31
Si esto siempre fuera cierto, la pregunta original no se habría hecho. Tome, por ejemplo, un StackPanel horizontal con una etiqueta y un cuadro de texto. Hay espacio adicional a la derecha de TextBox. TextBox está configurado en Ancho automático. Establecer Stretch para HorizontalAlignment no hará que TextBox llene el espacio restante.
Brent Schooley
Nada es siempre cierto, pero esta respuesta funciona para mis necesidades: DockPanel, Image.
alehro