Windows 8.1 XAML Wrap Stackpanel Children - xaml

I have a bunch of listviews inside a Stackpanel with a horizontal orientation. I want the lists to wrap once the reach the end of the Stackpanel.
This seems easy to me but I cannot seem to figure out how.

StackPanel does not wrap. Look at WrapGrid instead.

You can't do it using a StackPanel as the container. Usually I use a Grid as the parent container. It's more flexible.
Something like this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListView Grid.Column="0"/>
<ListView Grid.Column="1"/>
<ListView Grid.Column="2"/>
</Grid>

You can try it with an ItemsControl and use WrapGrid as its ItemsPanel template. Here is the code i am using:
<ItemsControl Width="Auto" Height="Auto" IsHitTestVisible="False" ItemsSource="{Binding AnnotationTypesShown}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Height="50" Width="Auto" Margin="0,0,5,0">
<Image Source="{Binding IconImage}" Stretch="UniformToFill" Margin="0,0,0,0" Width="25" Height="25"/>
<TextBlock Text="{Binding TypeName}" Width="Auto" Margin="5,10,5,0" Style="{StaticResource DefaultTextBlockStyle}"></TextBlock>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Orientation="Horizontal" VerticalAlignment="Top"></WrapGrid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Here is the result on full view
and in wrapped view

Related

SOLVED Pressing on ScrollViewer inside ListBox Item doesn't select the Item

I gave a ListBox that lists items. The items, can vary in size, but follow the same pattern:
picture................Metadata
ID
<ListBox Name="View" Grid.Row="2" ItemsSource="{Binding Human, ElementName=uc}"
SelectedItem="{Binding SelectedHuman, ElementName=uc}"
MouseDoubleClick="OnSubjectEditClick"
VerticalContentAlignment="Center"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.ScrollUnit="Pixel"
ScrollViewer.CanContentScroll="True"
Grid.IsSharedSizeScope="True"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate >
<DataTemplate >
<Border BorderBrush="#565656" BorderThickness="1" Margin="10" Padding="10">
<Grid>
<Grid.RowDefinitions>
<RowDefinition MaxHeight="300" />
<RowDefinition MaxHeight="50" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" MinWidth="300" MaxWidth="500" SharedSizeGroup="col1"/>
<ColumnDefinition MaxWidth="500" Width="*" SharedSizeGroup="col2"/>
</Grid.ColumnDefinitions>
<Image Grid.Row="0" Grid.Column="0" MaxHeight="300" MaxWidth="300" Source="{Binding Thumb}"/>
<TextBlock Grid.Column="0" Grid.Row="1" Text="{Binding Name}" FontWeight="Bold" TextAlignment="Center"/>
<local:MetadataView Grid.Column="1" Grid.RowSpan="2" Metadata="{Binding Metadata}" HorizontalAlignment="Stretch" VerticalAlignment="Center" IsEdit="False" />
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The items inside Metadata .xaml looks like this. StackPanels containing actual Metadata are automatically generated by code inside "DisplayMode":
<Grid VerticalAlignment="Center" HorizontalAlignment="Stretch">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" CanContentScroll="False" Height="300" >
<StackPanel x:Name="DisplayMode" VerticalAlignment="Center" Grid.IsSharedSizeScope="True" >
...........
<StackPanel/> //AutoGenerated
............
</StackPanel>
</ScrollViewer>
</Grid>
The problem I'm facing is the fact, that I need to be able to select an item inside the ListBox. But, by adding ScrollViewer in Metadata.xaml it seems I Reroute the selector, so it is trying to select an item in Metadata ScrollViewer instead of ListBox when I press the part of the ListBox containing Metadata. If I press on Thumbnail, or even RightClick on any part of the ListBox - it seems to select just fine.
[SOLVED] After playing around with available options in ScrollViewer I stumbled across Focusable. Setting it to False did the trick.
I hope it will help someone in the future.
<Grid VerticalAlignment="Center" HorizontalAlignment="Stretch">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" CanContentScroll="False" Height="300" Focusable="False" >
<StackPanel x:Name="DisplayMode" VerticalAlignment="Center" Grid.IsSharedSizeScope="True" >
</StackPanel>
</ScrollViewer>
</Grid>

UWP - Can I bind a textblock in a datatemplate to a grid column's width outside of it?

Relatively new to UWP, is it possible to bind a TextBlock of a DataTemplate (used for ItemTemplate in a listview) to a column outside of it, or is there any way to set the DataTemplate's grid columns' widths to the size of the "MainGrid"'s column definition widths? Code below to show what I'm trying to achieve.
<Grid x:Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="Column1" Width="*"/>
<ColumnDefinition x:Name="Column2" Width="8*"/>
<ColumnDefinition x:Name="Column3" Width="*"/>
</Grid.ColumnDefinitions>
<ListView Name="recordList" ItemsSource="{x:Bind _recordingList, TargetNullValue=0}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Recording">
<Grid>
<TextBlock Grid.Column="{Binding Column1}" Name="TextBlock_Time" Text="{x:Bind Time}"/>
<TextBlock Grid.Column="{Binding Column2}" Name="TextBlock_Message" Text="{x:Bind Message}"/>
<TextBlock Grid.Column="{Binding Column3}" Name="TextBlock_Type" Text="{x:Bind Type}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
With the image below, I suppose imagine the red lines are the window. Essentially trying to get the columns to adapt to the window size changing.
example
I think you want listviewitem to be streched to the size of window. To achieve that you need to set HorizontalContentAlignment of listviewitem has to set to stretch in ItemContainerStyle
<ListView x:Name="MessagesList" BorderThickness="1" ItemsSource="{x:Bind _recordingList, TargetNullValue=0}" BorderBrush="Black">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
<Setter Property="Padding" Value="0"></Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Recording">
<Grid BorderThickness="0,1,0,0" Padding="20" BorderBrush="{ThemeResource SystemControlForegroundBaseMediumBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="8*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{x:Bind Time,Mode=OneWay}"></TextBlock>
<TextBlock Grid.Column="1" Text="{x:Bind Message,Mode=OneWay}"></TextBlock>
<TextBlock Grid.Column="2" Text="{x:Bind Type,Mode=OneWay}"></TextBlock>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
You just need to move your columns to the template itself.
DataTemplate is a scheme that describes what and where. Because it's in ItemTemplate , then it means it's for every item.
<ListView Name="recordList" ItemsSource="{x:Bind _recordingList, TargetNullValue=0}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Recording">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="Column1" Width="*" />
<ColumnDefinition x:Name="Column2" Width="8*" />
<ColumnDefinition x:Name="Column3" Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
Name="TextBlock_Time"
Grid.Column="0"
Margin="20"
Foreground="Red"
Text="{x:Bind Time}" />
<TextBlock
Name="TextBlock_Message"
Grid.Column="1"
Margin="20"
Foreground="Green"
Text="{x:Bind Message}" />
<TextBlock
Name="TextBlock_Type"
Grid.Column="2"
Margin="20"
Foreground="LightBlue"
Text="{x:Bind Type}" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
That should make your items look like this.
Check out documentation, as it's explaining it nicely. There are templates in templates. So you can template a Container (how it should display items), and Items (how every item should look like).
Templates
Remember about HorizontalAlignment="Stretch" etc. as this means that the textblock (or Grid) will occupy all of it's space available (horizontally). Tinker with it and you'll get a grasp on how it works.

Full height of content in listview with ItemsWrapGrid as panel template windows 10 app

I am trying to have the content of gridview cell to stretch the height so there is no scrolling within the cell.
Here's my code:
<Grid Grid.Row="1" Padding="50 10 50 10">
<ListView IsTapEnabled="False"
Background="White"
SizeChanged="categoryListView_SizeChanged"
x:Name="categoryListView"
Height="auto"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ItemsSource="{Binding Source={StaticResource stores}, Path=CollectionGroups}"
ItemTemplate="{StaticResource CategoriesList}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
</Grid>
and here is my data template:
<DataTemplate x:Key="CategoriesList">
<Grid x:Name="AlphabetGrid" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0 0 20 0">
<TextBlock x:Name="CategoryName" FontSize="24" Text='{Binding Group.Key}' Foreground="#412141" FontWeight="Bold" HorizontalAlignment="Left" TextAlignment="Left"/>
<Grid Margin="0 30 0 0">
<ListView ItemsSource="{Binding Group.Items}" HorizontalAlignment="Stretch" VerticalAlignment="Top">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Margin="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="4*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" x:Name="unit_number" FontSize="15" Text='{Binding unit}' Foreground="red" HorizontalAlignment="Left" TextAlignment="Left"/>
<TextBlock Grid.Column="1" x:Name="name" FontSize="15" Text='{Binding name}' Foreground="red" HorizontalAlignment="Left" TextAlignment="Left"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Grid>
</DataTemplate>
How can I achieve this? Any recommendations?
This is how it looks right now.
I can reproduce your issue: it seems that ItemsWrapGrid uses some strange logic when row heights are calculated automatically. You can set its ItemHeight property manually to avoid this problem, but this solution is far from being elegant.
Alternatively you can use the WrapPanel XAML Control from the UWP Community Toolkit as an ItemsPanelTemplate for your ListView to make the items stretch their height to fit the content
<ListView>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<controls:WrapPanel/>
<ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ListView>
however, your grid is going to have a lot of empty space then
If that's not what you want, you can eliminate most of the empty spaces by changing the orientation of the WrapPanel from horizontal to vertical
and even further by not grouping your items into separate controls by category

ListView is not Scrollable

I have the following ListView in my xaml layout:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<TextBlock Text="{StaticResource AppName}" Style="{StaticResource TitleTextBlockStyle}"/>
</StackPanel>
<StackPanel Grid.Row="1">
<ListView x:Name="lstStatus">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="12">
<Image Source="ms-appx:///Assets/Logo.png" Margin="12" Width="150" Height="150"></Image>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Path='Fullname'}" Style="{StaticResource ListViewItemSubheaderTextBlockStyle}"></TextBlock>
<TextBlock Text="{Binding Path='FormattedCreationTime'}" TextWrapping="WrapWholeWords"></TextBlock>
<TextBlock Text="{Binding Path='Text'}" Style="{StaticResource ListViewItemContentTextBlockStyle}" TextWrapping="WrapWholeWords" Margin="12"></TextBlock>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</Grid>
However, I met two problems:
The list is not scrollable when it is longer than the screen.
The TextBlocks does not wrap at all although I already set TextWrapping.
I am pretty new to Windows Phone design. Please tell me where did I do wrong.
The StackPanel takes as much space as it needs. As the ListView grows, the StackPanel expands to allow it to grow, hence you cannot scroll to see the items you don't see on the screen.
Put the ListView in a Grid or limit the Height of the StackPanel.
<Grid Grid.Row="1">
<ListView x:Name="lstStatus">
...
Similar problem occurs in your ItemTemplate, and the fix is also similar.
<DataTemplate>
<Grid Margin="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image ...
<StackPanel Grid.Column="1">
<TextBlock ....
</StackPanel>
</Grid>
</DataTemplate>

GridView with 2 items in each row

I want to show two GridViewItems in each row, with equal width. how can I achieve that?
I am using following template but it is not taking equal space between items.
<DataTemplate x:Key="GridViewItemTestTemplate">
<StackPanel Orientation="Horizontal">
<Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}" Margin="0,9.5,0,0">
<Image Height="79" Width="79"/>
</Border>
<StackPanel Grid.Column="1" Margin="14.5,0,0,0">
<TextBlock Text="{Binding Title}" Style="{ThemeResource ListViewItemTextBlockStyle}"/>
<TextBlock Text="Subtitle" Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
here is my gridview.
<GridView ItemsSource="{Binding MyData}" ItemTemplate="{StaticResource GridViewItemTestTemplate}"
IsSwipeEnabled="False" SelectionMode="Single" HorizontalContentAlignment="Stretch">
</GridView>
Replace your StackPanel with this
<Grid Grid.Column="1" Margin="14.5,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Title}" Style="{ThemeResource ListViewItemTextBlockStyle}"/>
<TextBlock Grid.Column="1" Text="Subtitle" Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}"/>
</Grid>
Grids resize themselves dynamically versus StackPanels. The ColumnDefinition Width="*" is the important part, telling the panel to set the width of each column to fill the width of the grid, and for each column to have the same width.
edit: Is this the hehavior you want? Not as pretty as dynamic resizing but the same width requirement with 2 items per row basically force all items to have the same width
<GridView Width="200">
<GridView.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="Width" Value="80" />
</Style>
</GridView.ItemContainerStyle>
...
</GridView>