I want to arrange two UIControls vertically. The top one is variable height while the bottom one is fixed height. How can I make the top element stretch to available height in a StackPanel or Grid?
My question is similar to this question, and the answer suggested the use of DockPanel, however in WP8 there's no DockPanel, so is there any other alternative of that?
A Grid can do that with a row-height of "*" - i.e. a Grid with two rows, the top one "*" the bottom one "auto" would do the trick (not verified for Win8 but should work if memory serves)
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
...
</Grid>
Related
I worked with WinForms and there was an option to create TableLayoutPanel.
For example: I need that my window devided to two parts top and bottom, and I would like that top part take 70% of the window and bottom part 30% of the window...
Now, I am working with WPF and according to this
https://www.codeproject.com/Articles/30904/WPF-Layouts-A-Visual-Quick-Start
there are in WPF a lot of different layouts, but I did not find any that has the same bihaiour as TableLayoutPanel - that I can set how many rows I need and how much of the window should each row take.
How to do it?
To achieve the same behaviour as TableLayoutPanel you can use the Grid control in WPF, it allows you to define as much columns and rows as you need, XAML works very differently than WinForms when designing.
You can add them through the grid properties window under the layout section, specifically ColumnDefinitions and RowDefinitions.
As you begin adding rows, you will see that the width or height of the element is 1 unit of star (which is its default value), this is a special value that helps in distributing the width and height equally among all members of a RowDefinition or ColumnDefinition collection in the available space of a control. You can make a column or row take more available space by incrementing the value of stars the intended row is expected to take.
To give an example, if you have a grid with 3 columns and 2 rows, all with default values, you will have the following XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
</Grid>
And in the designer, you will see the following grid:
As you can see, all the available space is divided equally between all the columns horizontally and all the rows vertically, if you would like to have a column take more space, you could give it a value of 2 stars, and it will take the space that 2 stars should take.
In that case, the XAML will look like this:
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
</Grid>
And your designer will look like this
There are more options for width values:
Auto: This option will resize itself to fit its children dimensions.
Pixel: This option will make the dimension take up as much pixels as specified (the real dimension can vary slightly, but that's out of scope of this answer)
Now, when you want to put elements inside the grid, you can do so in the designer, or in the xaml, the element that is placed in the first row and first column, will have no tags, but in case you want to put the elements in the second column of the second row, your XAML would look like the following;
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="1" Grid.Column="1">
</TextBlock>
</Grid>
The values Grid.Row and Grid.Column specify in which column and row you want to place the element and are zero-based indexes.
I believe this pretty much sums up all you need to know to get started, WPF has a learning curve (which some say it is a wall) that once you learn it, developing UI becomes trivial, unlike winforms.
I am trying to add UserControl to MainWindow. And I want to set property of the Screen resolution of the controls also automatically. Please help me for that screen
Please be more clear while asking a question. Do you want the user control to fill inside your window or you want to re-size the window width to the size of the control within it?
If you want the user control inside the window to fit inside the window you could use the same width as the window excluding the border for the user control or use "*" for the user control width so that it can occupy the entire space.
If you want responsive layout, then you should divide UI proportionally. As a consequence of this, you can set proportion what you want and this proportion will be resized proportionally depending on your display size. For example, you have FooUserControl:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="5*"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="4*"/>
</Grid.ColumnDefinitions>
<local:FooUserControl Grid.Row="1" Grid.Column="1"/>
</Grid>
The size of Height and Width can have three values:
Fixed - it is fixed size. (1/96 inch)
Auto - it takes as much space as needed by the placed control
Star (*) - the available width/height is divided evenly among all columns/rows proportionally.
I'm having trouble getting the two ListViews to adjust their height to the containing window. I am using a GridSplitter between them. I want one ListView to shrink and one to grow when i drag the GridSplitter.
Here is the stripped down xaml code.
<Grid x:Name="Gridthing">
<Grid.RowDefinitions>
<RowDefinition Height="150"/>
<RowDefinition Height="10"/>
<RowDefinition Height="150"/> <!--bottom-->
</Grid.RowDefinitions>
<ListView Name="Things1" Grid.Row="0"/>
<GridSplitter Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="LightGray"></GridSplitter>
<ListView Name="Things2" Grid.Row="2"/>
</Grid>
However in this example the bottom ListView always 150 tall regardless of what size the window is set too.
Now I can already hear a thousand voices screaming use "*" or "auto" for the the height of the bottom grid row.
However that has a worse problem. The bottom ListView now extends passed the window and has no scroll bar, rendering anything not in the window invisible.
I am looking for a way that allows the two ListViews to take up all the space in the window with a GridSplitter in between and always displays the scroll bar.
Thanks for any help.
The Problem was that my grid was in a userconrol inside a stackpannel inside the main window. I had to swap out the stackpannel for a grid in the main window and then it performed perfectly. thanks dkozl.
I have a seemingly simple layout problem in Windows Phone. The problem is illustrated in the image below:
My requirements are as follows:
Subtitle must always be visible, at the expense of the overflowing text of the title.
Title and subtitle together must be vertically and horizontally centered.
When I use a StackPanel or auto-height Grid rows, the box will overflow. If I try star height rows
I can't control a large title.
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock ...>Title</TextBlock>
<TextBlock Grid.Row="1" ...>SubTitle</TextBlock>
</Grid>
Found the solution, this will cover everything except the bottom element overflowing the whole screen, in my case this won't be possible. It only works if the parent container does not have infinite height provided (like a StackPanel).
Basically, auto height takes 'precedence' over star-height elements. This gives the bottom TextBlock room to choose its height, and then assigns the remaining available space to the top element.
When debugging my WPF programs I have noticed that when the window is the set size, the contols look just fine. But when the window is maximized, the content is positioned at the same place as if window has not resized. I want it so that the content and window resize proportionately. How can I do this? Sorry if it is a noobish question, but I'm kinda new in the WPF era.
The XAML code is not completely ready yet but here is some of elements:
<DockPanel>
<StackPanel DockPanel.Dock="Left">
...
</StackPanel>
<TabControl DockPanel.Dock="Right">
...
</TabControl>
<ListView>
...
</ListView>
</DockPanel>
Usually, this is because dimension values are set statically, rather than dynamically. Here's the static approach:
<RowDefinition x:Name="NavigatorRow" Height="120"/>
<RowDefinition x:Name="TaskPanelRow" Height="80"/>
Both rows will have fixed heights, and they won't resize with the window.
Here is the dynamic approach:
<RowDefinition x:Name="NavigatorRow" Height="1*"/>
<RowDefinition x:Name="TaskPanelRow" Height="80"/>
The bottom row still has a fixed height of 80, but the top row will expand to fill whatever space is available. In other words, the rows will resize with the window. Columns work the same way.
If I had three rows, I could do this:
<RowDefinition x:Name="NavigatorRow" Height="1*"/>
<RowDefinition x:Name="CalendarRow" Height="2*"/>
<RowDefinition x:Name="TaskPanelRow" Height="80"/>
The Navigator Row and the Calendar Row will share the available space, with the Calendar Row taking twice the height of the Navigator Row. You get the idea.
So, it's not the container you use, but how you size that container. The one exception, as noted above, is the StackPanel, which does not scale. Use a Grid instead, since it does scale.
Usually this is because the content is hosted in a container which has an explicitly set width and height - like Grid for example.
Post your Xaml or that answer is the best you will get!
Avoid using StackPanels they don't resize dynamically properly.
Ideally you should use a grid and specify percentages if you want things to resize proportionately.
Not sure why everyone is saying stackpanels don't resize dynamically. They handle resizing just like grids do. Just make sure you set your HorizontalAlignment="Stretch" (and/or VerticalAlignment) and the content will expand to fill the stackpanel size. I'm currently using a UI that consists of many nested stackpanels, horizontal and vertical resizing the window expands/contracts all the controls equally inside the window.
Well, you have to have some sort of container for your controls, right? If you're using Canvas and just position your controls absolutely inside there you're pretty much out of luck; this isn't very well for scaling interfaces.
However, there are various container controls that will layout whatever you put in them in certain ways. And if used properly, they scale with a resizing window, too. The Grid is pretty flexible, but StackPanel and DockPanel are very handy at times, too.
You can nest them, if you need.
Use WPF grid with the Widht and Height properties setupped with the "Number*" notion.
For example Width="0.6*", wich is not absolute height but proportional relation to the container. Generaly , if you want resizable content, avoid the fixed size properties as much as you can.
<Grid.RowDefinitions>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="*" ></RowDefinition>
</Grid.RowDefinitions>
Good Luck.