Search code examples
wpfuser-interfacelayout

How to get controls in WPF to fill available space?


Some WPF controls (like the Button) seem to happily consume all the available space in its' container if you don't specify the height it is to have.

And some, like the ones I need to use right now, the (multiline) TextBox and the ListBox seem more worried about just taking the space necessary to fit their contents, and no more.

If you put these guys in a cell in a UniformGrid, they will expand to fit the available space. However, UniformGrid instances are not right for all situations. What if you have a grid with some rows set to a * height to divide the height between itself and other * rows? What if you have a StackPanel and you have a Label, a List and a Button, how can you get the list to take up all the space not eaten by the label and the button?

I would think this would really be a basic layout requirement, but I can't figure out how to get them to fill the space that they could (putting them in a DockPanel and setting it to fill also doesn't work, it seems, since the DockPanel only takes up the space needed by its' subcontrols).

A resizable GUI would be quite horrible if you had to play with Height, Width, MinHeight, MinWidth etc.

Can you bind your Height and Width properties to the grid cell you occupy? Or is there another way to do this?


Solution

  • Each control deriving from Panel implements distinct layout logic performed in Measure() and Arrange():

    • Measure() determines the size of the panel and each of its children
    • Arrange() determines the rectangle where each control renders

    The last child of the DockPanel fills the remaining space. You can disable this behavior by setting the LastChild property to false.

    The StackPanel asks each child for its desired size and then stacks them. The stack panel calls Measure() on each child, with an available size of Infinity and then uses the child's desired size.

    A Grid occupies all available space, however, it will set each child to their desired size and then center them in the cell.

    You can implement your own layout logic by deriving from Panel and then overriding MeasureOverride() and ArrangeOverride().

    See this article for a simple example.