WPF - automatically relocating children when parent resizes - wpf

I have a container whose size can change.
I will by dynamically creating instances of a user control and adding them to that container.
the size of the user control is fixed. what I want to do is, fit the most number of user controls in the container.
I think a good approach is to add the children horizontally until there is no more space to add another and then start another row.
Say, each row fits 3 children for a given width of the container. if it is expanded enough, it should automatically fit 4 children in a row.
Is there a container control (StackPanel Grid etc.) that I can use to host these user controls. What properties need to be changed.
On resizing the container, it should relocate the children so that the maximum children ae shown. Scrolling is okay as long as max are shown at any given time.
Is there a container that does this automatically? or should I manually create rows or panels or something and add n children to each - i.e., do it manually?

I think what you need is a WrapPanel.
There's a Panels Overview on the MSDN with a lot more information and links to specific types of Panel including the WrapPanel:
WrapPanel positions child elements in sequential position from left to right, breaking content to the next line at the edge of the containing box. Subsequent ordering happens sequentially from top to bottom or right to left, depending on the value of the Orientation property.

I think a good approach is to add the children horizontally until there is no more space to add another and then start another row.
This is exactly what a WrapPanel does.

Related

Silverlight zindex with dynamically added controls

I have grid with some textboxes and an image which goes out of grid boundaries and I add this grids dynamically in my code to another grid.
I want to have my image on top of all the rest of the grids. Unfortunately each grid I add to the root grid will hover over my previous grid image.
Could you please suggest anything?! I have tried with zindex and it did not work in my case.
What I am doing wrong?
ZIndex only works for the immediate children of a panel-derived container (Grid, Canvas, Stackpanel etc). Otherwise it is down to the order they exist in the visual tree (i.e. the last one gets displayed on top).
If you have nested objects you simply need to think about the order they are added. The simplest way to do this is have two top level grids/panels, the first contains everything else and the last containing just the dynamically added children.
This way whatever you put in the second grid will always be on top of all other items (in the first grid/container).

Is there an alternative to a WPF WrapPanel that wraps after a certain number of items, not a height?

Normally a WPF WrapPanel (Orientation="Vertical") will stack items vertically (and grow vertically) until it runs out of space from the parent container, and then it will "wrap" to the next column.
I want this functionality, but I want to add a hard limit to the number of items in a column. For instance, if my height is 100 and I have 3 items that are 30 pixels high, normally it could fit them all without wrapping. However, say I want to force it to wrap after 2. In that case, I want it to only grow to a height of 60, and wrap the 3rd item into the second column.
Is there something I can do to make this happen?
Maybe you can do it with the UniformGrid.
Use the Rows property to definie the amount of elements in vertical direction.
here is a nice little article about the available layout panels in WPF. If one of these does not fit the bill, you might have to build your own custom panel, here is a decent demo.

Silverlight: how to use a scroll viewer to wrap a list view without specifying height?

I have a control that has a list that varies in length greatly. This control appears in various places meaning that i cannot calculate its position and desired height easily.
Moreover all I want is for the scrollviewer to simply size itself according to its parent. currently it insists on sizing itself according to the content.
currently when i have a list that exceeds the height of the screen the whole control extends off the bottom and the scrollviewer shows no bar (because it has stretched to the heigth of the contents and so thinks it is not required).
I've not included code as the object graph is fairly deep.
What i am looking for is a set of conditions that would cause the scrollviewer to resize itself according to its content rather than its parent.
I have it working in a similar situation involving grids and datagrids, the unique part of this control is that there is a list containing controls.
Any ideas? I would prefer solutions that don't require use of code behind - but im really not in a position to be choosey.
Here are common reasons that come to mind that would allow a scroll viewer to size to its contents rather than to its "parent":-
It's placed on a Canvas or a StackPanel
It's assigned to a Grid row/column with it's Horizontal or Vertical alignment not set to Stretch and its content size is less than the size of the row or column.
Its ultimately upto the containing panel how it chooses to size a child element so its not really possible to dictate this completely from code inside the child.

Get airport display type transition when data changes

A client has asked for a display to flick over like an airport display screen, ie each row flicks over when information changes.
I am not sure which is the best control to use, or the method of getting each row to transform one after the other.
any suggestions woul b gratfully accepted
John
Here's what I would do in general concept..
Make a regular panel of, say 50px high. (This is arbitrary but this panel just holds the size in place so the control doesn't shrink with its contents.)
Create a panel inside that one that will be the 'animated' panel.
When it's time for information to animate, create a storyboard that uses a transformation to "stretch" the height down to 0, change the content to the updated information, then tranform stretch the height back to 50px. This will create the illusion that the panel is flipping over.
If you make this a user control, then you could simply add however many "rows" you needed of this control to a StackPanel to make your screen.
The best way of representing this effect easily is to randomize the text during the change.
Patrick Long implemented this effect as a custom animation here

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