wpf: resizing a control according to its content - c#

I have a control that inherits from Grid, it is a grid of hexagons that are generated dynamically according to the properties.
each of the hexagons is a button and a child of the Grid, and they have a style that displays them as hexagons.
what I want is for the grid to change its size according to the total size of the hexagons.
(I can calculate the exact size needed, but I don't know how to set it).

Basically you've got several options. A simple one is calculating the size yourself and assigning to the Grid's Width and Height.
A more elaborate solution would be to ask yourself a question: which layout is needed for my items? There are some standard containers which do the layout themselves and can grow/shrink with the content. For example, if your objects are just aligned in a line, you can go for StackPanel.

Related

C# WPF Dynamic Scaling with MinHight/MinWidth Set to Auto

The title pretty much describes what I am looking for. I have found answers that are close but not quite what I need. I am hoping someone can explain how to do this or point me in the right direction.
Current setup:
I have multiple user controls. Each contain a grid that has 5 rows and 3 columns. First row definition is set to Height="Auto" and the rest are Height="". First column definition is set to Width="Auto" and the others are set to Width="". I do not want the first row and first column to ever change size but I would like to have the rest of the grid scale.
Question:
I am trying to create a window, which contains a grid, that will dynamically size. The grid contains user controls stated above and each row and column in the window is set to *. I do not want any element in the window to size below what is required for the inner controls (i.e. I do want a button control change sizes but it should never become smaller then Auto width or height). Is there a way to allow for this scalability but do not get any smaller then what the controls requires (ideally within the xaml)?
I don't remember the exact CSS syntax, but I was hoping xaml had something similar to the way CSS sizes content equal to the size of characters on the screen (i.e. Min-Width: 1.5m;)
If you wanted the first row and column to be a static size then don't set them to auto, set the actual size then for the rest of the columns/rows you could use * so they all remain equal

How to get the Width/Height of a collapsed control in WPF?

im wondering if theres an easy way to get the width of a control in WPF at runtime while the control is collapsed.
when i use control.Width ill get the following result: -1.#IND
and control.actualWidth will return 0.0 because its collapsed.
i want to resize my window and then display the collapsed control.
thanks
Edit:
Some details
i have a grid with 2 columns in my window, the 1st column holds a tab control, the 2nd column holds an expander control. i want to extend the width of my window when expanding the expander control, so the content in the 1st column will remain its size.
Put the control in question inside a container (like a ContentControl) and collapse the container rather than the control itself. Then you should be able to simply call Measure (or use the DesiredSize property) on the control to determine how much room it wants.
What size do you expect to get?
The size is not just dependent on the control but also on its container. So the actual size can not be determined unless the control is actually rendered.
Instead of using Collapsed you could make it Invisible that way it will be sized by its own logic and the logic of the container.
EDIT
In the comments it became clear that what the reason was for needing the size of the control:
I have a grid with 2 columns in my
window, the 1st column holds a tab
control, the 2nd column a holds an
expander control. i want to extend the
width of my window when expanding the
expander control, so the content in
the 1st column will remain its size.
My answer:
Set the SizeToContent of the window to WidthAndHeight and set the width of both grid columns to auto. That should take care of it.
I believe you're going about this the wrong way. You can set the Window Width and height to "Auto" and then it will take care of all the resizing stuff.
The problem arises whenever you directly set the Width property of any control(trust me I've done it). Once you do that, you've told WPF hands off of resizing logic, I know what I'm doing.
If you think something isn't resizing at the right time you can add a handler to some event and then call control.InvalidateVisual() or control.InvalidateMeasurement() which will make it go through a whole new layout pass.
You have to call the UpdateLayout method on the control or conainer of control. After that the things may work properly.
In UWP you can determine size of collapsed control by making it visible for a sec and then hiding it again, change is not noticeable:
var oldVisibility = myBorder.Visibility;
myBorder.Visibility = Visibility.Visible;
myBorder.UpdateLayout();
var height = myBorder.RenderSize.Height;
myBorder.Visibility = oldVisibility;
Post which is marked as an answer actually does not answer the question, it just gives a workaround.
To get the size of the collapsed control you need:
Set control's visibility as Hidden (Collapsed won't evaluate).
Call Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)) method of the control.
Get the size from DesiredSize property of the control.
Then you can Collapse your control back.

How to adjust WrapPanel height dynamically based on content?

I'm developing a WPF application. In this application, I have a Window which contains a WrapPanel. Inside the WrapPanel are a series of StackPanels which have varying heights, but all the same width. The number and size of the StackPanels is not known at design time (they are generated dynamically).
These StackPanels normally stack fine on top of each other, and then "wrap" to another column when there is no more room in the WrapPanel. To achieve this, I had to set a fixed height for my WrapPanel (with the height set to "Auto", it would continue down the page instead of wrapping to another column). However, when by chance I have a StackPanel that is too large to fit in the WrapPanel height, it is simply truncated. An image of this situation is below.
My question is, can I query the height of each StackPanel before I Show() this to the user, and set the WrapPanel height based on the largest StackPanel? Is there a better way to do this?
First, have you ensured that this issue is not caused by the WrapPanel reaching its maximum available dimensions (i.e. if its size is being constrained by its parent Window or element)? Because if this is the case, then you'll need to either look at restructuring your overall layout, or wrap it in a ScrollViewer.
If the above is not the case, and the WrapPanel has plenty of room to 'grow', this does indeed seem like a strange issue. You say the StackPanels are generated dynamically. So in your code, you must be calling myWrapPanel.Children.Add(stackPanel). After this line of code, you could try adding something like the following:
myWrapPanel.Height = myWrapPanel.Children.Cast<FrameworkElement>().Max(e => e.ActualHeight);
EDIT: just realized this will only work if a single StackPanel takes up the entire height, as in your image. but perhaps it will start you on the right track!

SizeToContent on UserControl

In fact the UserControl lacks the property 'SizeToContent' that we have in Window.
So the question is:
what's the easiest and right way to simulate SizeToContent=WidthAndHeight behavior on UserControl?
UPD... yeah I know it suppose to get that automatically if no Height and Width defined in the container where you're placing a user control.
But it doesn't work when you placing one userControl with defined sizes, into another with no sizes, and altogether they go inside the container.
it this case your second control will take all the space it can get.
Use a Grid and set either the Row and Column height to * for the items you want to size to the window.
Just don't set the Width and Height properties. It will then take on whatever width and height its child requires.

Grid row height adjustment

I have two Expanders in a grid, both in Auto sized rows.
When the height of the Expander is very large, the row overflows out of the grid.
Is there a way to have Auto sized rows that take only the grid space that's available?
Try setting the MaxHeight property on either the expander object or the object inside the expander.
You could use a DockPanel instead - and then dock the first Bottom and let the other fill. Or put each Expander inside a ScrollViewer.
i would set the last rowDefinition to Height="*",
then the last row fills out all the space left.
but it doesnt help if not only the last row would overflow..
See my custom auto-sizing panel/grid class here. I wrote it specifically to address this problem--full source is in the question.
(To use it, create a new class that inherits from panel and paste the working code into the class, then use the custom class just like a StackPanel.)
It currently only supports Vertical orientation, but could easily be modified to support Horizontal as well.

Categories