I'm working on some layout stuff with XAML/C# and for certain reasons I am unable to use the SizeToContent="Width" option however I would like to simulate it in certain situations. I have a user control sitting inside of an expander and I would like to be able to get the ActualWidth of that user control so that when the expander is expanded I can increase the size of the GridColumn and window accordingly. Because the Expander starts off as IsExpanded="False" the ActualWidth property reads as 0.0. Is there any way I can get the ActualWidth of the user control as if it were fully visible and SizeToContent="Width" were in effect?
I've been trying desperately to figure out how to calculate this width without hardcoding the actual value. DesiredSize.Width and RenderedSize.Width also both return 0.0 when the expander is collapsed
I believe that if you run a Measure & Arrange pass, passing in an infinite Size, you'll be able to get the DesiredSize.
var infiniteSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
control.Measure(infiniteSize);
control.Arrange(new Rect(infiniteSize));
correction:
As mentioned in the comments, just calling Measure() with infinite Size does the trick; do not use Arrange().
Related
Basicaly i am trying to set the window size automatically to the minimum size before the scroll bar appears, logically I am thinking that if I set the size of the window to this size and all the components should be shown no problem, I tried a couple of the answers answering the other questions but that didn't work, minimum size is 0.
When I start up my application it doesn't show the full content, i am using a telerik report viewer(if anyone knows what it is) in a radform, but don't mind the names, the report viewer and radform are just extensions of the known winform and component so the same rules apply.
The thing is when I show the window it won't show the full component, it's mostly the horizontal scrollbar I need to remove by resizing the window.
I tried outputing the autoscrollminize property on both the form and the component but they are both 0,0 however if the scrollbar appears and disappears when I resize the window manually there should be a property/value somewhere I could use to set the windowsize from the start.
technical info:
the component is already docked
if I undock the reportviewer component the scrollbar appears inside this component so the key is to figure out when the vertical scrollbar will appear depending on the data in this component
I already tried
setting the autosize property to true for the window and setting the size to 10,10
finding minimum size/AutoScrollMinSize
Setting the size to preferred size(when I do this the window takes on the absolute smallest possible size showing only the title bar.)
the form minimus size is the minimum size that YOU set on the form, it's not a minimum value calculated for you.
You need to calculate/find-out the space needed by your controls, and then you'll have a value to set in the form height/width.
For calculating the space needed by your controls, it's up to you: maybe rows numbers multiplied by row height + header/footer height? or something like that.
You can even do some different research: if there are scrollbar, somewhere there is already the value you need, you only need to find it out.
For doing this kind of research there is a tiny free tool that is very useful
Hawkeye - The .Net Runtime Object Editor - http://hawkeye.codeplex.com/
It works like a property grid, but you can hook it to running .net programs, and it show you everything (properties value, private field value, object reference...) so you can try to dig in the scrollbars object to see if you can find out your height/width value.
I have Image control in my Window. The size of this Image control is set to "Auto".
<Image x:Name="videoImg" Stretch="Fill" Height="Auto" Width="Auto" />
When i try to get access, it returns 0. How to see real size of this control? It resizes with window.
You can use .ActualHeight and .ActualWidth to get the rendered Height/Width of a control
The thing is, the Width and Height properties let you express the desired size, whereas what you want is the rendered size - which can be accessed (but not set) using the ActualWidth and ActualHeight properties.
It should be noted that these aren't static values either, that is, once set they are not necessarily going to be the same forever after, as it will be re-evaluated upon each rendering sequence...
Because [ActualHeight / ActualWidth] is a calculated value, you should be aware that
there could be multiple or incremental reported changes to it as a
result of various operations by the layout system. The layout system
may be calculating required measure space for child elements,
constraints by the parent element, and so on.
So, depending on your requirements, you might want to consider re-evaluating your data at appropriate points, perhaps when the containing control resizes, for instance.
While some of WPF controls fill up all available space when laid out and rendered, the others don't.
Specifically, the Image control is not of a kind that establishes its size on its own, i.e., in cases when you do not specify control's size explicitly with width/height attributes or the like.
But the Grid control fills up all available space when lacking size-defining attributes. The Page/Window template in Visual Studio has a Grid control as a child of a Page/Window root control, and when the user starts to put controls on a page in a graphical editor, the user-added controls first become children of this Grid control.
If you have used the VS template, and your Image control is a child of the said Grid control, name your Grid with an x:Name attribute, and you can use the Grid's ActualWidth/Height properties for your needs in a code-behind, because the image control grows up to its parent Grid size -- provided you do not specify its size explicitly or otherwise, i.e., setting the Image content.
By the way, the sizing behavior of built-in controls can be changed. You can modify a control and override corresponding dependency properties. See, for example, https://stackoverflow.com/a/6094993 .
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.
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!
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.