WPF: Control that never causes children to NOT consume all available space - wpf

Right now I have a problem with StackPanels inside DockPanels. Often the StackPanel is taller than necessary for the contents, so the contents are stretched.
Is there something I can place in or around the StackPanel to mean "don't cause children to consume all avaialble space".

AFAIK the contents of the StackPanel do not "stretch" to fill it, anymore than any other control. i.e. the stretch to fill will be controlled by the HorizontalAlignment and VerticalAlignment of the child elements.
The default is usually Stretch. Try setting it to Left etc.

Well, what do you want your StackPanel to do? If you want it to only consume the visible space, use a grid. If you want to scroll the contents of your StackPanel, I believe you can put it in a ScrollViewer.

Related

WPF Stretch Middle Content in DockPanel or Stackpanel

How do I stretch the content in the middle section of a Stackpanel or Dockpanel. I know that a dockpanel will stretch the last item but I need to stretch the middle item. I know that I could use a grid with * for the middle section but I want to be able to set the left and/or right items as collapsed depending on my window size.
You should still use a DockPanel with LastChildFill setted.
Your DockPanel will stretch the last element you put in it, not the last one according to view.
So you can put the element you want to stretch in the last position and use DockPanel.Dock="Top/Bottom/Right/Left" on others one.

How to make a WPF ScrollViewer use only the available width?

I have a wpf window, and there is a footer sections that can have multiple content which makes the width of the footer grows.
I set SizeToContent="WidthAndHeight" in my Window and when I add a lot of content to ScrollViewer, it grows accordingly, instead of just show the scrollbar.
It looks like ScrollViewer is taking into account its content, so how do I set the ScrollViewer to ignore it's content and only take the width available instead of make it grow?
thanks!
I suspect that by setting SizeToContent="WidthAndHeight" you tell the controls inside the window that they "can have all the space they want", so the ScrollViewer does not do anything becase it is not being restricted by its parent which is a necessary condition for a ScrollViewer to work (and make sense).
Try setting the MaxWidth property of the ScrollViewer. Once it has reached this width, it should start showing scrollbars.

Silverlight 4/WPF - Nested ScrollViewer panel that scales with available screen size

In the Windows Forms world you can take a panel and set it's dock property to fill and so on with nested panels, when the user resizes the window the panels and nested panels automatically resize too. I want to achive something similar with Silverlight, here is my current structure.
Main
ScrollViewer // for body
UserControl
Grid
control
Scrollviewer // this is where my problem is
Control
The problem is I can set a size for the nested scroll viewer that looks good for 1024 resolution, but I also want to account for users that have larger resolution. If I leave it auto the content just stretches below the visible bottom line and defers to the top level ScrollViewer.
If I could achieve something analogous to how Windows Forms handles this with docking I think my problem would be solved. I must have a ScrollViewer for the nested panel and I want it to fill all visible space left. How Can I achieve this with SL4 or WPF?
[Edit]
Here is an illustration of what i'm after.
The top-level ScrollViewer allows its content to be as large as it needs to be, and adds scrollbars if that means they don't fit in the window. Its children no longer know or care how tall the window is; they just know that they've got as much space as they want.
So what is it that you want from your nested ScrollViewer? It's got all the space it needs, so it will grow to show all of its content -- there's nothing to restrict it to the height of the window. In fact, you added a top-level ScrollViewer, which specifically told it "don't restrict it to the height of the window".
If you want your inner ScrollViewer to be restricted to the window height, then take out the top-level ScrollViewer.

Setting control height explicitly

I have a XamDataGrid in one of my user controls, inside of a stackpanel. I want the grid to maintain the same height regardless of how many rows are present in the grid. To do that, I set the grid's Height property to an explicit value.
Is that how things are done in WPF? Every time I do explicit sizing I feel like I am doing WinForms and not using WPF properly. Is setting the Height directly the only/correct solution?
There's nothing wrong with setting an explicit Height in situations where you want an element to always stay the same height. Where it's less appropriate is in situations where sizing is better handled by the parent layout Panel or the element's child content which can use the available space dynamically.
WPF uses a relative measurement system which at first glance is not intuitive. I have never found an example when I was forced to use explicit sizes ( once when I paint something on Canvas). I use styles in 90% cases where I define Padding, Margin, Aligment etc. Sometimes I use MinHeight and MinWidth for simple things.
About that Grid you can put it in the ScrollViewer or ViewBox to have dynamic sizing, yet If it won't be trouble set the explicit Height.

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?
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.
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.
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.
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.
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.

Resources