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.
Related
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.
I'm building a universal app and my Win8.1 app has to show a grid of items. Normally the grid consists of 3 columns, but on smaller screens I want the items to wrap so that there are only 2 columns (or even 1). This is my code:
<GridView ItemsSource="{Binding Regions}" IsItemClickEnabled="True">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal" MaximumRowsOrColumns="3" MinWidth="400" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="10">
<Image Source="{Binding Code, Converter={StaticResource FlagIconConverter}, ConverterParameter='/Assets/Icons/Flags/{0}.png'}" Width="30" />
<TextBlock Text="{Binding NativeName}" Style="{StaticResource BodyTextBlockStyle}" Margin="10,0,0,10" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
Whenever I make the app smaller, the items do not automatically wrap. I tried solving this by changing the MaximumRowsOrColumns property with a VisualStateManager but that didn't work because it couldn't access my WrapGrid for some reason. Changing the property from code-behind didn't work either, because again it couldn't access the WrapGrid.
I tried this with both WrapGrid and ItemsWrapGrid (what is the difference anyway?) and ListView and GridView. No difference there.
Does anyone know how to accomplish this?
You shouldn't need to do anything. It should wrap based on the available client area. The only thing I can think of that would not make it wrap is that you put your <GridView> inside a fixed width container or a container that is size Auto in which you don't update the Observable Collection to notify the Grid to redraw/update itself.
For example this will not wrap.
<Grid Width="1000">
<GridView x:Name="myGridView" IsItemClickEnabled="True">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal" MaximumRowsOrColumns="5"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<!-- DATATEMPLATE -->
</GridView.ItemTemplate>
</GridView>
</Grid>
However get rid of that Width=1000 and it will wrap.
Example output 3 different sizes
I have a LongListSelector where each item can contain variable number of images and hence can be of different height. Here's my XAML:
<phone:LongListSelector x:Name="Views" ItemsSource="{Binding}">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding Imgs}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="#44AAAAAA" Margin="10,0,10,10">
<Image Source="{Binding photo.Source}" Stretch="UniformToFill"
Height="{Binding Converter={StaticResource ScaleHeight}, Path=photo}" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
The problem is while scrolling such LongListSelector when I come across a long item, the scroll position suddenly jumps a few items forward/backward (depending of scroll direction).
I suspect this has something to do with virtualization but I don't know how this can be fixed. Any suggestions?
You should use the Grouped version of the LongListSelector with an empty header, like this you will not have items with such different Height.
I can not figure out what I did wrong. I have a Usercontrol that has a vertical progressbar and under it a label.
<UserControl x:Class="IFramedInBrowser.Code"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" Height="150" Width="15">
<Grid Width="120" Height="15" >
<StackPanel Width="120" Height="15" >
<ProgressBar Grid.Row="0" Value="{Binding Path=Percent}" Maximum="100" Width="120" Height="15" />
</StackPanel>
<TextBlock Grid.Row="1" Height="30" HorizontalAlignment="Left" Name="textBlock1" Text="{Binding Path=Symbol.Name}" VerticalAlignment="Top" >
<TextBlock.RenderTransform>
<RotateTransform Angle="90"/>
</TextBlock.RenderTransform>
</TextBlock>
<Grid.RenderTransform>
<RotateTransform Angle="-90"/>
</Grid.RenderTransform>
</Grid>
</UserControl>
This usercontrol is then used in a ItemsControl
<ItemsControl x:Name="HorizontalListBox"
ItemsSource="{Binding Source={StaticResource MyViewModel}, Path=List}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center" Height="150"
>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<my:Code DataContext="{Binding}">
</my:Code>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
It should look like a piano keybord at the end...
After the rotation transformation the progressbar is chopped... What did I dowrong? How to fix this?
You can try to add different background colors to all controls to find out sizes of controls.
Also SilverlightSpy is now free for read only and you can go through the real visual tree at runtime.
Anyway, I would suggest to change the orientation of ProgressBar by customizing its template.
This is a clipping issue. You are setting too many heights and widths everywhere and it's confusing to know which one is in control of dimensions. Also, the stacking in the ListBox works on the layout and the RotateTransform is only effective on the final visual pass, so it's rotating a clipped progress bar.
You should follow jumbo's advice and create a vertical progress bar by modifying the template, not by rotation.
If you don't want to create the template, then you need to remove the main Grid you have in the UserControl and use a Canvas instead. Canvases don't clip. They let your elements float freely, which is probably what you want.
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.