I want to make a simple layout:
This is my code:
<ScrollViewer Grid.Column="1" Grid.Row="1" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Disabled" VerticalContentAlignment="Stretch">
<StackPanel Name="MainStack" Orientation="Horizontal">
<StackPanel Width="800" Height="800" Margin="140,0,10,0" Background="#FFAC3737"/>
<StackPanel Width="400" Height="800" Margin="0,0,10,0">
<StackPanel Width="400" Height="395" Background="Black" HorizontalAlignment="Left" Margin="0,0,0,10" />
<StackPanel Width="400" Height="395" Background="Black" HorizontalAlignment="Left" />
</StackPanel>
<StackPanel Width="400" Height="800" Margin="0,0,10,0">
<StackPanel Width="400" Height="395" Background="Black" HorizontalAlignment="Left" Margin="0,0,0,10" />
<StackPanel Width="400" Height="395" Background="Black" HorizontalAlignment="Left" />
</StackPanel>
<StackPanel Width="400" Height="800" Margin="0,0,10,0">
<StackPanel Width="400" Height="395" Background="#FF5686AE" HorizontalAlignment="Left" Margin="0,0,0,10" />
<StackPanel Width="400" Height="395" Background="#FF5583AA" HorizontalAlignment="Left" />
</StackPanel>
<StackPanel Width="400" Height="800" Margin="0,0,10,0">
<StackPanel Width="400" Height="395" Background="#FF5180A8" HorizontalAlignment="Left" Margin="0,0,0,10" />
<StackPanel Width="400" Height="395" Background="#FF426E93" HorizontalAlignment="Left" />
</StackPanel>
</StackPanel>
</StackPanel>
</ScrollViewer>
Now It looks like this:
What is the best way to scale this layout to all resolutions ?
Grid is a great control for specifying how you want to use available space. I like to use * (star) sizing and think of each * as a percentage. So, if I want two columns to each take up 50 percent of the screen, their widths would be 50* and 50* (though technically as long as they're equal numbers they'll take up equal space so 1* and 1* would do the same thing).
The problem with Grid is that it tries to use all the space you give it. So, if you design a layout on a square monitor (4:3 aspect ratio) then display it on a widescreen monitor (16:9 aspect ratio) all your squares become rectangles!
You could sort of deal with this in code by monitoring whenever the size changes and making sure that the width is always some percentage of the height. But that's an ugly fix and leaves one more challenge to contend with: font size.
Many times when you're creating a very specific layout you want it to scale perfectly to all screen sizes, including text. But just because Grid adapts to the available real estate doesn't mean that the font size will automatically scale up too. That is, unless you use ViewBox.
ViewBox is an awesome control. You can put anything inside of it with a specific width and height, and as the available space for the ViewBox increases or decreases, it automatically scales everything inside of it. ViewBox maintains the correct aspect ratio for you and automatically does font scaling too!
So, start with a Grid and give it a specified width and height, then divide the rows and columns to make it look like your image above. Start at whatever width and height you want, but I suggest 1366 x 768 because that's the lowest recommended resolution for Windows 8. Finally, wrap the Grid in a ViewBox and you're done!
<ViewBox>
<Grid Width="1366" Height="768">
...
</Grid>
</ViewBox>
Dev support, design support and more awesome goodness on the way: http://bit.ly/winappsupport
I think StackPanels not the best choice for complex layout. I'd use Grid with different Width/Height ratios for different columns/rows with span columns/rows when needed. Then you will have elastic layout for every resolution.
Related
I have a UWP where I am loading from an XML file and showing it in a GridView and I am trying to enable Scrollbars in a way that allows me to stack and wrap items in all the available space like in the image below. The problem that I am having is that I cannot figure out how to enable the scrollbars so that I can scroll the boxes until I get to the end of the list.
So far I have got it to do what you see in the picture, which is wrapped the way I want but it fills all the available space and doesn't allow you to scroll vertically or horizontally (I only want to scroll one way but I have tried to see if I could go either way). Through a lot of trial and error I was able to get it to scroll one row or one column at a time to the end of the list but that is not the desired result either. Here is where I am with the XAML right now (trimmed down version of the screen shot).
<GridView x:Name="DataGrid1">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal"
ScrollViewer.HorizontalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollBarVisibility="Disabled" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate>
<Border Width="270"
Height="200"
Margin="5"
BorderBrush="Black"
BorderThickness="2">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70" />
<ColumnDefinition Width="100*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="2"
Background="#87CEFA">
<TextBlock Margin="2"
HorizontalAlignment="Center"
FontSize="16"
FontWeight="Bold"
Text="{Binding Company}" />
</StackPanel>
<TextBlock Grid.Row="1"
Grid.Column="0"
Margin="2"
HorizontalAlignment="Right"
FontWeight="Bold"
Text="Code: " />
<TextBlock Grid.Row="1"
Grid.Column="1"
Margin="2"
Text="{Binding Code}" />
</Grid>
</Border>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
So what do I need to do to enable the scrollbars the way that I want?
Make sure your GridView is in a Grid and not a StackPanel. It does not expand in a StackPanel.
To make it scroll in a StackPanel you have to specify the height of the GridView. This was the issue with mine :)
To my knowledge gridviews that are not showing scrollbars automatically are due to stackpanel's presence. So my solution here is to try remove stackpanel what so ever, and if I find the stackpanel that's responsible replace it with other kind of panel and work my way back up. It's totally a brute force kind of approach but it works most of the time.
And another piece of advice. In that process of replacing the stackpanel try to replace it with grid and try to divide it's rows and columns with widths and heights set to auto or star sizing instead of specifying it with actual numbers to see if it works this way. If it works then work your way up speicifying it with actual numbers.
Here's your problem, in the definition of the ItemsWrapGrid you have:
ScrollViewer.VerticalScrollBarVisibility="Disabled"
this is going to mean that even if the scrollbar is shown it wont work.
Remove this line and you should get a working scrollbar.
Got a GridView that its items width are set by the first one width(Screenshot)
How could I set some auto width for each item?
<GridView ItemsSource="{x:Bind PopularItems}" Style="{StaticResource GVStyle}" Height="230">
<GridView.ItemTemplate>
<DataTemplate x:Name="GVTemp" x:DataType="models:LessDetails">
<StackPanel>
<Image Height="180" Width="132" Source="{x:Bind Img}" />
<TextBlock Margin="4,4,0,4" HorizontalAlignment="Stretch" TextAlignment="Center"
Text="{x:Bind Name}" Style="{ThemeResource BodyTextBlockStyle}" />
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
You can not auto-width each item in a GridView control, it is by designed to use the first item's size as the uniform size (ListViewItemPresenter for each items has the same size).
For the auto-size scenario, I suggest you using the StackPanel or creating a custom ItemsControl.
Use an ItemsStackPanel:
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
The only downside is that it doesn't wrap items.. For that you can use the ItemsWrapGrid but then you lose the auto-width functionality (first item determines the width of all items).
There's also the VariableSizedWrapGrid that can be used by giving items a certain ColumnSpan/RowSpan, but it's not quite the same as automatically calculating the width.
If you want the best of both world, probably you'll need to write your own custom panel.
UPDATE: For a solution that allows for both automatic width and item wrapping, you can use the WrapPanel control from the UWP Community Toolkit.
is it possible in XAML to separate in a StackPanel control (or any container in general) rows and columns with lines? So that it looks for example like a chessboard? And also when the user resizes the window, the panel would also resize.
The only one of the built in Panels that draws lines is a Grid with ShowGridLines="True" set on it but the lines drawn are just kind of ugly dashed lines that can't be changed and are really only good for debugging purposes.
To draw your own lines you can just add an identical border into each cell, or each row or column if you want them to stretch across the whole layout. The easiest way to do a chessboard layout is with a UniformGrid:
<UniformGrid Rows="2" Columns="2">
<Border BorderBrush="Gray" BorderThickness="1" />
<Border BorderBrush="Gray" BorderThickness="1" />
<Border BorderBrush="Gray" BorderThickness="1" />
<Border BorderBrush="Gray" BorderThickness="1" />
</UniformGrid>
For a full board you can save typing and use an ItemsControl bound to some 64 item collection with a template for the lines:
<ItemsControl ItemsSource="{Binding ListOf64Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Gray" BorderThickness="1"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="8" Columns="8"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
There are also lots of possible variations depending on what exactly you want out of the grid.
In the following XAML, the word "Test" centers horizontally but not vertically.
How can I get it to center vertically?
<Window x:Class="TestVerticalAlign2343.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowStartupLocation="CenterScreen"
Title="Window1" Height="768" Width="1024">
<DockPanel LastChildFill="True">
<Slider x:Name="TheSlider"
DockPanel.Dock="Left"
Orientation="Vertical"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Minimum="0"
Maximum="10"
Cursor="Hand"
Value="{Binding CurrentSliderValue}"
IsDirectionReversed="True"
IsSnapToTickEnabled="True"
Margin="10 10 0 10"/>
<Border DockPanel.Dock="Right" Background="Beige"
Padding="10"
Margin="10"
CornerRadius="5">
<StackPanel Height="700">
<TextBlock
Text="Test"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="200" x:Name="TheNumber"/>
</StackPanel>
</Border>
</DockPanel>
</Window>
A stackpanel, no matter how you stretch it, will collapse around the children. you can't make it grow more than that. Basically, that "Height=700" is not helping you.
So either set VerticalAlignment on the StackPanel to "center" so that the stackpanel goes into the center of the dockpanel...or remove the stackpanel altogether and set VerticalAlignment="Center" on the TextBlock.
Seems I asked this question 10 months ago, I got the above scenario to work by replacing the StackPanel with DockPanel LastChildFill=True like this:
<DockPanel LastChildFill="True">
<TextBlock
DockPanel.Dock="Top"
Text="Test"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="200" x:Name="TheNumber"/>
</DockPanel>
I stumbled across this which seems to work perfectly:
<Grid>
<TextBlock Text="My Centered Text"
TextAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
The Grid ensures that the single TextBox within it fills the solitary cell in the grid and the VerticalAlignment in the TextBlock ensures that the text is centered within than.
Simply position/align your text horizontally however you require (the above snippet centers it in this axis also, but changing this doesn't alter the vertical centering).
Inside the StackPanel that surrounds the TextBlock, check out VerticalContentAlignment.
In XAML, I want the button to go on the BOTTOM of the red rectangle.
I clearly say:
"HorizontalAlignment="Right"
VerticalAlignment="Bottom"
It goes to the right but stays on the top. Why is that?
alt text http://tanguay.info/web/external/buttonTop.png
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MultiplePages.Page"
Width="300" Height="150">
<StackPanel HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Width="300" Height="150" Orientation="Vertical">
<StackPanel Width="300" Height="100" Background="Blue">
<TextBlock x:Name="theTextBlock" Text="This is page one. This is page one. This is page one. This is page one. This is page one. This is page one. This is page one. This is page one. This is page one. This is page one. "
TextWrapping="Wrap" Height="100" Width="300" HorizontalAlignment="Left"/>
</StackPanel>
<StackPanel Width="300" Height="50" Background="Red">
<Button Name="Switch" Content="Switch Page" Width="100" Height="20"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"/>
</StackPanel>
</StackPanel>
</UserControl>
The StackPanel is meant to take it's sizing from it's elements and it's container (depending on it's orientation), although what you've done looks correct, that's not the way the StackPanel is "meant" to be used. Although it looks like it's the height it's set, it's actual height (that it uses for laying out child controls) is the size of it's content (the button). The StackPanel has it's uses, but if you are doing anything other than a simple stack of controls then you generally should be using something else.
You can fix it by either sticking a sized grid inside:
<StackPanel Width="300" Height="50" Background="Red">
<Grid Height="50">
<Button Name="Switch" Content="Switch Page" Width="100" Height="20"
HorizontalAlignment="Right" VerticalAlignment="Bottom"
/>
</Grid>
</StackPanel>
Or, for that particular layout, you might want to look at DockPanel, which will behave more like you would expect it to.