I have the following layout problem best explained here (apologies for the crude illustration)
Assume each control is implemented as a separate user control
I want behavior such that expanding the top right (green) control will render into view an expanded region wider than the initial (green) control's width and appear directly beneath it, with a width equal to the 2 controls in the first row (eg colspan of 2) while pushing down all the content beneath it
Assume initially there is a grid with 2 rows ..first row is some control and secondly the expandable control - the second row can have anything that will fill a colspan of 2 ..could be another layout container or user control with anything inside it etc.
If the green expandable control was a user control, what would I need to do to obtain this behavior I'm describing?
I'm thinking I need to set the Grid.Row and Colspan attached properties of the container representing the expanded content(?) from inside the user control to the layout grid the user control is inside? (but then how would I set the attached property of a control inside the user control to a layout container outside the user control - especially if the expanded content is itself inside a grid within the user control).
And even if I could do this, this would be very fragile since it would only work if the control was in a grid layout container.
Any ideas? Doesn't have to use a grid but that seems to be the natural / obvious way to solve it?
I had a similar layout a while ago. This worked for me:
On the green control, create dependency properties for the sizes you need. In this case, I expect the full width (lower rect) and the narrow width (upper rect).
In the top-level container, you create a grid for measuring the sizes. So you'll get something like this:
<Grid x:Name="fullSize">
<ColumnDefinition/>
<ColumnDefinition x:Name="halfSize"/>
</Grid>
Here you can divide the width over the columns in the appropriate way.
- Then, bind the widths measured with this grid
<foo:GreenControl
FullWidth={Binding ElementName=fullSize, Path=ActualWidth}
NarrowWidth={Binding ElementName=halfSize, Path=ActualWidth}
/>
Now the GreenControl can set its width to whatever it needs to be, e.g. in the handler for the value update. In my case I set bindings on the elements in the XAML to the dependency props.
Related
I'm working on a Windows Store App.
I have a ListView with a bunch of items in it. It is nested in some stack panels and grids, but they all essentially are auto sized. Essentially, the ListView is given most of the right half of the screen, regardless of what size it is.
If I give the ListView a hard-valued Height, a scrollbar will automatically appear with no extra work. Great. But I don't want to set a height... I want it to be all of the area available in its container. If I try to be clever and set it to 9999 or something then it will not scroll.
I've done a bunch of research, and similar questions like this say that the thing that holds the ListView cannot give it infinite size like a StackPanel would. What alternatives do I have? How can I put a ListView in something with arbitrary space and get a scroll bar to appear?
My only thought is that there must be some way to, in the container that holds the ListView, tell the ListView that it has all available area in such a way that it's height gets set that that value. Sort of like how to have to set ListViewItem's HorizontalContentAlignment property to 'Stretch' in order to get the items within a ListView to know what what available width they actually have.
The essential bits of my layout is this:
<!-- Nested in some other stuff simple Grids and StackPanels, none of which has hard heights set (all auto or *) -->
<!-- Even if I made this a Grid with one Row, setting definition to * or Auto doesn't help the issue - no scroll bar appears -->
<StackPanel>
<!-- Other stuff that has Visibility="Collapsed"... I have code so that only one item at a time within this container will ever be visible, and it gets all available space. -->
<ListView ItemsSource="{Binding SomeBigList}" ItemTemplate="{StaticResource MyDataTemplate}" />
<!-- Other stuff that has Visibility="Collapsed" -->
</StackPanel>
How can I get a scrollbar to appear in the ListView without setting a hard height anywhere? Thanks for you're help.
Don't use a <StackPanel>.
If you are in control over what gets drawn and only one item is ever visible at any one time, then use a non-infinite sized container like <Grid>. You can put each item in the same row, or use a separate row if only for ease of spotting what's what.
I ran into similar on the Windows Phone app. You need to remove the variables of the other containers by creating a test page and determining which panel is causing your ultimate problem.
Create new blank page with a Grid and ListView.
Work the grid sizing to be automatic (auto) or * sized until you see the horizontal scroll bar.
Once the horizontal scroll bar appears, add the other containers, one by one until the scroll bar disappears. That will inform you of the culprit which is causing the miss-sizing and ultimately the failure of the scrollbar to appear.
What's the correct pattern to resize controls when a font size changes?
For example, I used the WPF designer to make a form, and placed UI elements from the toolbox. Late in the game I got the requirement that the font size of every UI element needs to be configurable, so now I'm thinking there has to be a better way to resize controls when the font size changes. Right now I'm doing alot of code behind calculations on Margin properties.
For such cases I usually place my control inside Grids and StackPanels, this way font size won't affect the layout, everything will be stretchable.
Never place controls on the Window using absolute coordinates.
Make sure your Height and Width on the controls are set to Auto.
When you use the designer/toolbox to add controls it usually provides a static height/width. If you type the tag in the XAML editor you get the control default which is usually Auto.
You'll notice the black diamond in the property window next to the attributes that are changed from their default value. You can right click and choose reset value to clear the attribute from your XAML and see what the default value is.
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.
I have an Expander control and i need to calculate its bounds without invisible elements and margins. It commonly can be done by VisualTreeHelper.GetDescendantsBounds. But it seems that the rect is calculated by VisualTreeHelper doesn't depend on the expander state. For example:
http://i.piccy.info/i5/58/39/273958/collapsed.jpg
(i can't post images. sorry)
The same result as for expanded state (light green rectangle on the image). Does anybody know how to solve this problem?
The Expander control will set its content's visibility to Collapsed, which means it won't be considered during layout and won't be included in GetDescendantBounds. However, the Expander can be forced to have a larger size by the layout engine, and the Expander's own size is included in GetDescendantBounds.
Try setting VerticalAlignment="Top" on the Expander. The default is Stretch, which will allow it to increase in size if the parent has more space available. Also make sure you aren't explicitly setting the Height property.
This is the sample application. The style is applied here to the TreeView control and its items. But the problem doesn't depend on the style.
It gets basicaly to this:
I have a canvas container (x:name="Container" - to reffer later to), with some other controls(e.g. I have a Button 30x60 in size) and I want to scale the Container to fit the button, without having to resize anything. (just using scaleTransform)
If I set a slider binded to the Container Scale, I can slide it to fit the button, but the value is 1.1343 and I want to be able somehow to compute this value programatically, because all the controls inside Container are of different sizes, and resizable in adition.
The question is: is there a way to scale the Container so that a Control from the container is displayed on the entire Container surface? Also the position will have to be adjusted, so that the scrolling vierew of the Container should be positioned over the control, but that is done already.
Thank you in advance,
Daniel
Use Grid as the container. Any control placed inside of the Grid will directly fill the whole Grid, and its size (the width and height) will match the size of the Grid.
It seems when you add a user control using a grid as a container, the usercontrol, which comprises a set of labels and an array of buttons will not align to the top but arranged somewhere in the middle.