How do I write the code that flows items in a GridView (XAML-Win8) group, according to the below illustration?
I currently have a custom TemplateSelector
that selects a different (larger) template for the first item, but the flow as specified here:
<GroupStyle.Panel>
<ItemsPanelTemplate>
<q42:WrapPanel Orientation="Horizontal" Width="440" Margin="0,0,80,0"/>
<!-- also tried VariableSizedWrapGrid -->
</ItemsPanelTemplate>
</GroupStyle.Panel>
Wraps items 1 through 3 similarly, but then places item 4 at item 6's position, without filling out items 4 nor 5.
Question becomes; how do I write code that acts similar to css:
.item { display: inline-block; }
.item1 { float: left; }
, which would make the items flow like I want?
Andreas Hammar linked me to a working solution:
using System.Collections.Generic;
using Application1.Data;
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace Application1
{
public class MyGridView : GridView
{
int _rowVal;
int _colVal;
readonly List<Size> _sequence;
public MyGridView()
{
_sequence = new List<Size>
{
LayoutSizes.PrimaryItem,
LayoutSizes.SecondarySmallItem,
LayoutSizes.SecondarySmallItem,
LayoutSizes.OtherSmallItem,
LayoutSizes.OtherSmallItem, // 5
LayoutSizes.OtherSmallItem,
LayoutSizes.SecondaryTallItem, // 7
LayoutSizes.OtherSmallItem,
LayoutSizes.SecondarySmallItem, // 9
LayoutSizes.OtherSmallItem,
LayoutSizes.SecondarySmallItem, // 11
LayoutSizes.SecondarySmallItem,
LayoutSizes.OtherSmallItem,
LayoutSizes.OtherSmallItem
};
}
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);
var dataItem = item as SampleDataItem;
var index = -1;
if (dataItem != null)
{
index = dataItem.Group.Items.IndexOf(dataItem);
}
if (index >= 0 && index < _sequence.Count)
{
_colVal = (int) _sequence[index].Width;
_rowVal = (int) _sequence[index].Height;
}
else
{
_colVal = (int) LayoutSizes.OtherSmallItem.Width;
_rowVal = (int) LayoutSizes.OtherSmallItem.Height;
}
VariableSizedWrapGrid.SetRowSpan(element as UIElement, _rowVal);
VariableSizedWrapGrid.SetColumnSpan(element as UIElement, _colVal);
}
}
public static class LayoutSizes
{
public static Size PrimaryItem = new Size(6, 2);
public static Size SecondarySmallItem = new Size(3, 1);
public static Size SecondaryTallItem = new Size(2, 2);
public static Size OtherSmallItem = new Size(2, 1);
}
}
<local:MyGridView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</local:MyGridView.ItemsPanel>
<local:MyGridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid Margin="1,0,0,6">
<Button
AutomationProperties.Name="Group Title"
Content="{Binding Title}"
Click="Header_Click"
Style="{StaticResource TextButtonStyle}"/>
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid ItemWidth="80" ItemHeight="160" Orientation="Vertical" Margin="0,0,80,0" MaximumRowsOrColumns="3"/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</local:MyGridView.GroupStyle>
</local:MyGridView>
I think it could be done with a VSWG. I've gotten halfway there but haven't hade time to finish it...
First you need to set the attached prop VariableSizedWrapGrid.RowSpan and ColSpan - and that has to be set on the item container, by inheriting the VSWG: http://blogs.u2u.be/diederik/post/2012/03/07/Databinding-to-the-VariableSizedWrapGrid-in-Windows-8-Metro.aspx
And in your case 2x2 for the first item, 1x1 on the rest.
The measuring of cell size is done on the first element, unless you specify the ItemHeight etc explicitly. So you have to accomplish this somehow :) http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/569e048a-9f5e-4fb3-870a-380de5906e80 WG supports single sized items and all items are shown at that same size. VSWG allows for variable sized items but the item sizes allowed are in integral multiples of the base cell size. WG and VSWG work in layout cells. The size of the layout cell is determined by ItemHeight and ItemWidth properties. If these properties are not set, then the size of the first item is used as the cell size and subsequent items are measured at that size for WG; for VSWG the item is measured in integral multiplication of the cell size based on RowSpan and ColumnSpan properties. It seems that you have to set the height and width of the VSWG in order to accomodate the size of the largest item if you don't want the item to be first in the list. --> this is the part that I did not get around to.
Lastly the horizontal orientation.
Good luck!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With