351

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?

David Refoua
  • 3,476
  • 3
  • 31
  • 55
Rune Jacobsen
  • 9,907
  • 11
  • 58
  • 75
  • 1
    UniformGrid is amazing, My new default goto tag. I liked the Stackpanels simplicity (reminds me of a div) but Uniform Grid does exactly what I need. – Terrance Aug 11 '12 at 23:10
  • 1
    Re UniformGrid. The emphasis is on Uniform. Seems that you can't adjust the column widths no row heights. It is only suitable if each piece of content is the same size. I replaced my StackPanel with a Grid, and Stretch then worked as I expected it to. – pdschuller Mar 27 '18 at 14:17
  • [This article](https://www.roelvanlisdonk.nl/2010/12/09/setting-100-width-and-100-height-for-a-textbox-in-wpf/) helped me stretch textboxes. – jpaugh Aug 12 '19 at 16:32

5 Answers5

276

There are also some properties you can set to force a control to fill its available space when it would otherwise not do so. For example, you can say:

HorizontalContentAlignment="Stretch"

... to force the contents of a control to stretch horizontally. Or you can say:

HorizontalAlignment="Stretch"

... to force the control itself to stretch horizontally to fill its parent.

Matt Hamilton
  • 200,371
  • 61
  • 386
  • 320
  • 114
    The most notorious panel mentioned in all of these cases is the StackPanel. It does not contain ContentAlignment properties and setting its children to Stretch will have no effect inside of a star-sized grid. Very frustrating. It's almost as if the StackPanel was the first container the WPF team wrote and it suffers for that being the case. – Brent Schooley Apr 24 '09 at 20:40
  • 4
    @Brent - ahh! I've been stuck on trying to get my stackpanel's contents fill correctly. thanks! I thought it was just something I was doing very wrong. – Ashley Grenon Oct 21 '10 at 17:02
  • 8
    @townsean Stack panel is very limited, you can get similar behaviour with stretching using a UniformGrid and setting either Rows or Columns to 0 – ForbesLindesay Aug 04 '11 at 16:15
  • 4
    @Tuskan360 UniformGrid only allows the cells to be the same size. I used a Grid in the end, seems to work. Annoying how StackPanel doesn't do what it's seemingly designed to. – TarkaDaal May 15 '12 at 16:14
  • 7
    @TarkaDaal yeh, UniformGrid if everything's the same size, Grid if you want to specify complex relative sizes, stack panel to just size based on the contents and ignore how much space is available. – ForbesLindesay May 15 '12 at 18:53
  • Bang, Bulls eye : ) Thanks a lot, exactly the piece of code i was searching all the time ! – Chandraprakash Aug 14 '20 at 12:42
  • Yes, StackPanel! It's the big boss of all evil. – cheny Apr 19 '22 at 06:16
  • DockPanel works for certain things. https://www.wpf-tutorial.com/panels/dockpanel/ I was trying to have a Textblock, Textbox that filled the middle space, and Button using a stackpanel, but by setting DockPanel.Dock to Right for the button and setting it in front of the textbox, the textbox wound up filling the in-between space. Not sure exactly what you(other people reading considering I'm 14 years late) need it for, but it might be a good way to go. – Marcus Jul 13 '22 at 22:45
175

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.

Martin Schneider
  • 14,263
  • 7
  • 55
  • 58
user3837
  • 2,236
  • 2
  • 15
  • 6
  • 6
    @user3690202 Archive.org is your friend. Link reanimated. – ruffin Jun 18 '16 at 17:54
  • 4
    The topic still exists in MSDN, but the link changed to this: https://learn.microsoft.com/en-us/dotnet/framework/wpf/controls/how-to-create-a-custom-panel-element – Andrea Antonangeli Jun 25 '17 at 12:44
  • 4
    `The last child of the DockPanel fills the remaining space`: this was the missing key to my understanding. I always though that the element without explicit Dock filled the space. – Spotted Jul 29 '19 at 14:47
  • but DockPanel doesn't have Orientation? As usual from GUI designers, "we're to clever to use a logical, simple system" "Lets force this crap on the next generation of coders" – Paul McCarthy Dec 28 '22 at 23:26
  • The last child of the DockPanel fills the remaining space - NO it does not – Paul McCarthy Dec 30 '22 at 13:16
  • The last child of the DockPanel fills the remaining space - Yes it does. But DockPanel has a property LastChildFill="False" which modifies this behaviour. – 75ntamas Feb 22 '23 at 12:39
26

Well, I figured it out myself, right after posting, which is the most embarassing way. :)

It seems every member of a StackPanel will simply fill its minimum requested size.

In the DockPanel, I had docked things in the wrong order. If the TextBox or ListBox is the only docked item without an alignment, or if they are the last added, they WILL fill the remaining space as wanted.

I would love to see a more elegant method of handling this, but it will do.

RJFalconer
  • 10,890
  • 5
  • 51
  • 66
Rune Jacobsen
  • 9,907
  • 11
  • 58
  • 75
  • 1
    I just want to point out (on this old question!) that "without an alignment" is a key phrase here, at least it was for me. – MikeBaz - MSFT Mar 26 '13 at 12:38
  • I'd love to know if visual form ide designers ever actaully ask programmers what they want? I haven't seen a good one since Delphi 2009 – Paul McCarthy Dec 28 '22 at 23:31
6

Use the HorizontalAlignment and VerticalAlignment layout properties. They control how an element uses the space it has inside its parent when more room is available than it required by the element.

The width of a StackPanel, for example, will be as wide as the widest element it contains. So, all narrower elements have a bit of excess space. The alignment properties control what the child element does with the extra space.

The default value for both properties is Stretch, so the child element is stretched to fill all available space. Additional options include Left, Center and Right for HorizontalAlignment and Top, Center and Bottom for VerticalAlignment.

urini
  • 32,483
  • 14
  • 40
  • 37
  • 36
    If this was always true, the original question would not have been asked. Take, for instance, a horizontal StackPanel with a Label and a TextBox. There is extra space to the right of the TextBox. The TextBox is set to Auto width. Setting Stretch for HorizontalAlignment will not make the TextBox fill the remaining space. – Brent Schooley Apr 24 '09 at 20:38
  • Nothing is always true but this answer works for my needs: DockPanel, Image. – alehro Jan 21 '20 at 07:38
  • "Nothing is always true" Entropy increases true is always true Thought this was a site for programmers? – Paul McCarthy Dec 30 '22 at 13:21
1

Use SizeChanged="OnSizeChanged" in your xaml and the set the sizes you want in the code behind.

private void OnSizeChanged(object sender, SizeChangedEventArgs e)
        {
            TheScrollViewer.Height = MainWin.Height - 100;
        }

Long term it will be better for you. When your manager comes along and asks "make that a bit bigger" you won't to spend the afternoon messing about with layout controls trying to get it to work. Also you won't have to explain WHY you spent the afternoon trying to make it work.

Paul McCarthy
  • 818
  • 9
  • 24