WrapPanel inside ListBox in UWP - xaml

I am looking to add WrapPanel inside my ListBox so that it's item wrap both vertically and horizentally. I was able to achieve this in Windows Phone 8 Sliverlight with Microsoft toolkit with below code;
Windows Phone 8
<ListBox x:Name="ListSection" ItemsSource="{Binding Section}" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel Orientation="Horizontal" ></toolkit:WrapPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="20">
<Image Source="{Binding ImagePath}" Width="80" Height="80"></Image>
<TextBlock Style="{StaticResource PhoneTextBlockBase}"
HorizontalAlignment="Center"
Foreground="Black"
Text="{Binding Header}"
FontWeight="Bold"
VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
I understand that Microsoft toolkit it not available in UWP, is there any possibility I could achieve such behavior in UWP?
UWP not working
<ListBox x:Name="ItemsListBox" ItemsSource="{Binding Section}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel HorizontalAlignment="Stretch"></StackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Image Source="{Binding ImagePath}" Width="80" Height="80"></Image>
<TextBlock HorizontalAlignment="Center"
Foreground="Black"
Text="{Binding Header}"
FontWeight="Bold"
VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Thanks!

You must use ListView and ItemsWrapGrid as ItemsPanel
you can check the MSDN docs here with examples
https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.itemswrapgrid.aspx
This example is for GridView but is the same for ListView
<GridView>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
you can use the property Orientation to set your items vertically or horizontally.

There is a port of the Toolkit's WrapPanel for UWP in the project WinRTXamlToolkit.
You can get it from NuGet.
Then in your Page add this prefix:
xmlns:toolkit="using:WinRTXamlToolkit.Controls"
Now you can use <toolkit:WrapPanel Orientation="Horizontal" ></toolkit:WrapPanel> as it was before.

#ARH you need to create a custom Panel class which inherits panel class and override MeasureOverride and ArrangeOverride methods.check out following links for reference.
https://msdn.microsoft.com/en-us/library/windows/apps/mt228347.aspx
http://www.visuallylocated.com/post/2015/02/20/Creating-a-WrapPanel-for-your-Windows-Runtime-apps.aspx

The WrapPanel is available from the Microsoft UWP Toolkit.
Here's some sample code (using v5.0.0):
...
xmlns:toolkit="using:Microsoft.Toolkit.Uwp.UI.Controls"
...
<ListView
Name="WrapPanelContainer"
Width="310" Height="200"
Margin="0,40,0,0"
HorizontalAlignment="Left"
Background="LightBlue"
IsItemClickEnabled="True"
>
<ListView.Resources>
<Style TargetType="ListViewItem">
<Setter Property="MinWidth" Value="0"/>
<Setter Property="MinHeight" Value="0"/>
<Setter Property="Padding" Value="0"/>
</Style>
</ListView.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel VerticalSpacing="10" HorizontalSpacing="10" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<Rectangle Fill="Red" Width="100" Height="50"/>
<Rectangle Fill="Blue" Width="200" Height="50"/>
<Rectangle Fill="Green" Width="50" Height="50"/>
<Rectangle Fill="Yellow" Width="150" Height="50"/>
</ListView>
NOTE: The ListItemView style here removes superfluous padding, allowing the WrapPanel spacing properties to be the control points for layout.

Related

How to get a UWP DataTemplate to use the sizing of it's ListView?

In the example below, the ListView control understands the width of it's parent container RelativePanel. When looking a the layout in the designer, it is clear that the ListView is filling out to the full width of the RelativePanel. However, even though the RelativePanel inside the DataTemplate is also asking to fill out the width of the parent, it ignores the "align left" and "align right". I can't seem to find any way to get it to recognize it's parent container's size.
Any suggestions here would be appreciated.
<RelativePanel RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True">
<ListView Name="LstOrders" ItemsSource="{x:Bind Vm.OrdersList, Mode=OneWay}"
SelectionMode="None"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
Margin="0,5,0,0">
<ListView.ItemTemplate>
<DataTemplate x:DataType="genericOrder:OrderThumbnailVm">
<RelativePanel Name="PanelThumbnail" Margin="0,0,20,0">
<RelativePanel Name="PanelOrderDetails"
Background="BlueViolet"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True">
<TextBlock Text="{x:Bind Name}" Margin="8,0,0,0" VerticalAlignment="Center"
Foreground="{x:Bind Deleted, Mode=OneWay, Converter={StaticResource DeletedColor}}"
TextWrapping="WrapWholeWords"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.LeftOf="BtnDeleteRestore"/>
<Button Name="BtnDeleteRestore"
Content="{x:Bind DisplayDelete, Mode=OneWay}"
Click="{x:Bind DeleteOrder}"
RelativePanel.AlignRightWithPanel="True"
FontSize="10"
Height="20"
Padding="0"
Visibility="{x:Bind ShowDeleteButton, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}"/>
</RelativePanel>
</RelativePanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</RelativePanel>
That is because the value of HorizontalContentAlignmentof ListViewItem is Left, we need to override it and make it Stretch. You can find it in the ListViewItem styles and templates.
To solve this problem, as I said, we need to override its style, for example like this:
<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate >
<RelativePanel>
...
</RelativePanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

GridView with two columns Win Phone 8.1

I am currently learning Windows Phone 8.1 app development. I am going through this Channel 9 series of video tutorials. They are useful but unfortunately are for Windows Phone 8, not 8.1 and so there are some things I can't follow. I am stuck in such a situation.
I want to have the following layout driven by some data:
So far I have the following code:
<Pivot x:Uid="Pvt">
<PivotItem Header="{Binding Animals.Title}">
<GridView ItemsSource="{Binding Animals.Items}">
<GridView.ItemTemplate>
<DataTemplate>
<!-- not sure what would go in here -->
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</PivotItem>
</Pivot>
But not sure what element I'm supposed to have in the <DataTemplate>!
Gridview works fine in Windows Phone apps. Here is code from one of my apps in the app store. You need to set the size of the outer most 'Grid' of the DataTemplate. You won't be able to get the grids to fit the screen exactly unless you do some dynamic sizing after the UI is loaded.
<GridView Grid.Row="2" Margin="0,0,0,0"
ItemsSource="{Binding InfoTypeList}"
SelectionMode="None"
IsItemClickEnabled="True"
ItemClick="GridView_ItemClick">
<GridView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Left" Width="120" Height="120">
<Border Background="{ThemeResource PhoneAccentBrush}">
<Image Source="{Binding ImagePath}" Stretch="Uniform" Margin="10,10,10,20"/>
</Border>
<StackPanel VerticalAlignment="Bottom">
<TextBlock Text="{Binding Name}" Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource BaseTextBlockStyle}" FontSize="18" HorizontalAlignment="Center" FontWeight="SemiBold" IsTextScaleFactorEnabled="False"/>
</StackPanel>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemContainerStyle>
<Style TargetType="FrameworkElement">
<Setter Property="Margin" Value="20 20 0 0"/>
</Style>
</GridView.ItemContainerStyle>
</GridView>
EDIT:
I played around with it and you can get it to look more like your picture (fit the items to the screen) by wrapping your GridView in a Viewbox and then limiting the number of rows by adding this to your GridView:
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Orientation="Vertical" MaximumRowsOrColumns="2" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
You will have to play around with your margins to get the correct spacing.

StackPanel Orientation stops page load

First to explain what I am doing here, I want to create a page that list a large number of grouped objects. Selecting an object binds that information to a display on the left. Everything works fine till I change the MainStack Orientation to Horizontal. Once that is changed the page no longer loads. No errors are thrown. When stepping through the process the code behind steps through as it should.
I know its the XAML but am baffled by the cause. It works fine under two circumstances.
If I drop the mainstack stack panel and instead make the display group the header of the GridView it works.
If I put the MainStack orientation to Vertical it loads fine.
Here is the code that does not load:
<StackPanel Name="MainStack" Orientation="Horizontal" Grid.Row="2" >
<StackPanel Name="Stack" Width="480" >
<TextBlock Text="{Binding Nname}" Margin="0,0,0,20" Style="{StaticResource SubheaderTextBlockStyle}" MaxHeight="60"/>
<TextBlock Text="{Binding Nset}" Margin="0,0,0,20" Style="{StaticResource SubheaderTextBlockStyle}" MaxHeight="60"/>
<Image Source="{Binding url}" Height="Auto" Margin="0,0,102,55" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
<ScrollViewer Margin="0,0,0,0" MaxHeight="200">
<TextBlock Text="{Binding Nruling}" Margin="0,0,0,0" Style="{StaticResource BodyTextBlockStyle}"/>
</ScrollViewer>
</StackPanel>
<SemanticZoom x:Name="semanticZoom" Width="Auto" >
<SemanticZoom.ZoomedOutView>
<GridView Foreground="White"
ScrollViewer.IsHorizontalScrollChainingEnabled="False">
<GridView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Group.Key}"
FontFamily="Segoe UI" FontWeight="Light" FontSize="24" />
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid ItemWidth="100" ItemHeight="100" MaximumRowsOrColumns="4"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="Margin" Value="4" />
<Setter Property="Padding" Value="10" />
<Setter Property="Background" Value="#FF25A1DB" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Bottom" />
</Style>
</GridView.ItemContainerStyle>
</GridView>
</SemanticZoom.ZoomedOutView>
<SemanticZoom.ZoomedInView>
<GridView
x:Name="itemGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Items In Group"
TabIndex="1"
Padding="120,126,120,50"
ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
SelectionMode="Single"
ScrollViewer.IsHorizontalScrollChainingEnabled="False" SelectionChanged="itemGridView_SelectionChanged">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid MaximumRowsOrColumns="8" GroupHeaderPlacement="Top" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate>
<Grid Height="110" Width="480" Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="110" Height="110">
<Image Source="{Binding url}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Nname}"/>
</Border>
<StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0">
<TextBlock Text="{Binding Nname}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap"/>
<TextBlock Text="{Binding Nset}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/>
<TextBlock Text="{Binding Nruling}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60"/>
</StackPanel>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemContainerStyle>
<Style TargetType="FrameworkElement">
<Setter Property="Margin" Value="52,0,0,2"/>
</Style>
</GridView.ItemContainerStyle>
<GridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}" Margin="10">
<TextBlock Text='{Binding Key}' Foreground="{StaticResource ApplicationForegroundThemeBrush}" FontSize="25" Margin="5" />
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</GridView.GroupStyle>
</GridView>
</SemanticZoom.ZoomedInView>
</SemanticZoom>
<!-- Horizontal scrolling grid -->
</StackPanel>

Windows Store App - XAML - Why is the Textblock is bigger the StackPanel?

I have the below XAML and it does not do what I expect it to do.
<StackPanel Background="{Binding EwsColour}" Visibility="{Binding EwsVisibility}" HorizontalAlignment="Center" VerticalAlignment="Center" >
<TextBlock Text="EWS" Style="{StaticResource SubheaderTextBlockStyle}" VerticalAlignment="Top" FontWeight="SemiBold" HorizontalAlignment="Center" />
<TextBlock Text="18" Style="{StaticResource SubheaderTextBlockStyle}" FontWeight="SemiBold" FontSize="100" />
</StackPanel>
I end up with this
I don't understand why the TextBlock that has 18 in, is growing bigger then then StackPanel. Can anyone tell me why?
After seeing Chris W''s comment I checked the Style in generic.xaml.
<Style x:Key="SubheaderTextBlockStyle" TargetType="TextBlock" BasedOn="{StaticResource BaseTextBlockStyle}">
<Setter Property="FontSize" Value="26.667"/>
<Setter Property="FontWeight" Value="Light"/>
<Setter Property="LineHeight" Value="30"/>
</Style>
I had no idea that there was a LineHeight property. Overriding it so that its the same as the font size (or bigger actually creates a better UX) stops this from happening.
<StackPanel Background="{Binding EwsColour}" Visibility="{Binding EwsVisibility}" HorizontalAlignment="Center" VerticalAlignment="Center" >
<TextBlock Text="EWS" Style="{StaticResource SubheaderTextBlockStyle}" VerticalAlignment="Top" FontWeight="SemiBold" HorizontalAlignment="Center" />
<TextBlock Text="18" Style="{StaticResource SubheaderTextBlockStyle}" FontWeight="SemiBold" FontSize="100" LineHeight="110" />
</StackPanel>

ListViewItem won't stretch to the width of a ListView

I'm currently designing a windows 8 store app using XAML but I have a minor sizing issue. I have a ListView with a DataTemple.
The code for my ListView & DataTemplate are below:
<ListView x:Name="listPageItems"
Grid.Row="1"
SelectionMode="Extended"
IsSwipeEnabled="False"
ItemsSource="{Binding Mode=OneWay, Source={StaticResource items}}"
ItemTemplate="{StaticResource NavigationItemTemplate}"
ScrollViewer.VerticalScrollBarVisibility="Visible">
</ListView>
<DataTemplate x:Key="NavigationItemTemplate">
<Grid Height="75">
<Grid.RowDefinitions>
<RowDefinition Height="1.6*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Rectangle Fill="White" />
<Rectangle Fill="{StaticResource SSEGreenBrush}"
Grid.Row="1" />
<Border BorderThickness="2"
BorderBrush="{StaticResource SSEGreenBrush}"
Grid.RowSpan="2" />
<TextBlock x:Name="textTitle"
Text="{Binding ClientName}"
Style="{StaticResource TitleTextStyle}"
Foreground="{StaticResource SSEBlueBrush}"
Margin="10,5,5,5" />
<StackPanel Orientation="Horizontal"
Grid.Row="1"
HorizontalAlignment="Stretch">
<TextBlock Text="Last Edit :"
Style="{StaticResource SubtitleTextStyle}"
Foreground="{StaticResource SSEBlueBrush}"
Margin="3,0,0,3"
VerticalAlignment="Center" />
<TextBlock Text="SurveyDate"
Style="{StaticResource SubtitleTextStyle}"
Foreground="{StaticResource SSEBlueBrush}"
Margin="3,0,0,3"
VerticalAlignment="Center" />
</StackPanel>
</Grid>
</DataTemplate>
The listview is within a grid column with a fixed width of 240.
When the view is displayed the ListViewItems don't stretch to the width of the ListView. I've tried setting numerous properties including the HorizontalContentAlignment but I can't seem to get the ListViewItem to stretch!
Can anybody help?
I'm using Visual studio 2012, C# 4.5 and developing a Windows store app.
Try adding the following to your ListView definition
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
The easiest thing to do is just adding HorizontalContentAlignment="Stretch" to the ListView. There normally is no need for anything more.