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.
Related
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'm new to Windows 8.1 development, so forgive me if the answer to this is obvious, but I've been beating on this for awhile, and can't get it to work. Here's the situation:
I made a UserControl in order to style a button as well as adding additional functionality to it. Here's the code for that:
<UserControl
x:Class="MyCalculator.CalculatorButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyCalculator"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d"
>
<!-- THIS GRID TAKES UP THE WHOLE WIDTH AND HEIGHT -->
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- THIS BUTTON TAKES UP THE WHOLE SIZE OF THE GRID -->
<Button
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
BorderBrush="Blue"
BorderThickness="1"
Background="AliceBlue"
Padding="0"
Content="How can I make this bigger?"
Foreground="Blue"
Grid.Row="0"
Grid.Column="0"
/>
</Grid>
</UserControl>
Here's what it looks like in the designer:
You'll notice that the Button appears to be centered both horizontally and vertically, and is rather small. However, when I click into the Button in the code, the entire size of the Grid (which takes up the whole 400 x 300 area in the designer) is filled by the Button.
So the Button is filling the Grid, which is filling the area. But the Border and Background of the Button is super-small, in the middle of the Button. Worse yet, it doesn't even stretch to contain the text. This is obviously not the desired look and feel.
What am I trying to get it to do? I want the AliceBlue button background to fill the entire Grid, which fills the entire 400 x 300 area. I'd like the 'How can I make this bigger?' blue Content string centered vertically and horizontally in the big swath of AliceBlue-ness that will result.
I've tried innumerable combinations of specifications of Margin, Padding, Height, Width, and other attributes on the Grid and on the Button. Nothing has affected the size or placement of the AliceBlue area of the Button.
Clearly I'm missing something. Can anyone help me understand what that is, and how I can format my button (or the UserControl in general) to look the way I want it to?
Thanks in advance for your help!
Instead of assigning a string value to the Content property have you tried to put in a TextBlock child element? This might give you more control Hi. Button has HorizontalContentAlignment and VerticalContentAlignment that you can set. And then you can modify the HorizontalAlignment and VerticalAlignment of the child TextBlock inside the button independently.
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.
I have a project that uses a DataGrid with a custom template so that I can add a special row to the bottom of the data rows. I would like this special row to be pinned under the last row but not as part of the ScrollViewer, such that it remains pinned under the last row until the bottom of the special row hits the bottom of the data grid, then I would like the rows region to size to the space inbetween and scroll accordingly, with the special row always visible.
So far, I have my special row as part of the ScrollViewer along with the RowsPresenter. Both the presenter and the special row are in auto-sized rows of a Grid within the ScrollViewer, with the ScrollViewer in a star-sized grid row so that the scrollbar will appear when it runs out of space. How do I get from this, where the rows and special row scroll together to where I want to be, where the rows scroll, but the special row is pinned at the bottom and always visible?
Although my example uses a DataGrid, I am sure this can be simplified down to just a scrollable element of varying height, and a control pinned beneath it. So far, I imagine I need a Canvas rather than a Grid to host my ScrollViewer and companion special row, with some logic to adjust heights and positions when the ScrollViewer grows (if I can detect that), but I haven't yet tried this. Is there a better way or is the Canvas approach the best one available?
I was able to solve this by using a Grid with two auto-sized rows; a row for the DataGrid and a row for my pinned row. I then monitor the sizing of the Grid and, upon resizing, look to see if the Grid's ActualHeight is greater than the screen real-estate it is given to occupy. If it is, I change the DataGrid's row to star-sized, which results in the pinned row appearing pinned to the bottom of the parent control and the DataGrid displaying a scrollbar for its rows. I change the row back to auto-sizing when more space is made available.
This would obviously work for any scenario where one row must always be on screen but must also be pinned to the bottom of another.
The pinning code looks something like this:
RowDefinition row = this.mainGrid.RowDefinitions[0];
if (row.Height.GridUnitType == GridUnitType.Auto)
{
if (this.mainGrid.ActualHeight > this.ActualHeight)
{
row.Height = new GridLength(1, GridUnitType.Star);
}
}
else
{
if (this.dataGrid.DesiredSize.Height < row.ActualHeight)
{
row.Height = GridLength.Auto;
}
}
First, create a Grid for the main control and the pinned control:
<Grid Grid.Row="0" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- The main control, that is about to stretch. -->
<sdk:DataGrid Grid.Row="0" ItemsSource="{Binding YOUR_COLLECTION}" />
<!-- The pinned control. -->
<TextBlock Grid.Row="1" Text="Hello World" />
</Grid>
The trick is VerticalAlignment="Top" - when the main control is smaller than the available height, it will move to the top of the available space and the pinned control will appear under it.
Then, put this Grid into a container that stretches vertically, for example in a row of another Grid with Star height:
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<!-- RowDefition for the Grid with the main control and the pinned control. -->
<!-- If you want to have some other controls, -->
<!-- add other RowDefinitions and put these controls there. -->
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- The internal Grid for the main control and the pinned control. -->
<Grid Grid.Row="0" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<sdk:DataGrid Grid.Row="0" ItemsSource="{Binding YOUR_COLLECTION}" />
<TextBlock Grid.Row="1" Text="Hello World" />
</Grid>
</Grid>
Instead of the root Grid you may have any other container that stretches vertically, the important thing is that it tries to fill all the available space for it.