I am trying to insert several StackPanel inside the WrapPanel as you can see the XAML below:
Only the TextBlock inside the StackPanel will be modified so as not to repeat the Title and Text.
<Window x:Class="ambient_test.MainWindow"
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"
xmlns:local="clr-namespace:ambient_test"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<ScrollViewer CanContentScroll="True">
<WrapPanel x:Name="wrappanel">
<StackPanel x:Name="panel1" Width="120" Margin="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="120"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Background="#FF38C59F"></StackPanel>
<TextBlock Grid.Row="2" Text="Title 1" Foreground="LightGray" VerticalAlignment="Top" TextAlignment="Center"/>
<TextBlock Grid.Row="1" Text="Text 1" Foreground="#FF747474" TextAlignment="Center" Margin="0 15 0 0"/>
</Grid>
</StackPanel>
<StackPanel x:Name="panel2" Width="120" Margin="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="120"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Background="#FF38C59F"></StackPanel>
<TextBlock Grid.Row="2" Text="Title 2" Foreground="LightGray" VerticalAlignment="Top" TextAlignment="Center"/>
<TextBlock Grid.Row="1" Text="Text 2" Foreground="#FF747474" TextAlignment="Center" Margin="0 15 0 0"/>
</Grid>
</StackPanel>
</WrapPanel>
</ScrollViewer>
</Grid>
</Window>
I created a class called Info to change the Title and the Text. In the method constructor I have a for loop that will add 10 contents to the List.
public MainWindow()
{
InitializeComponent();
List<Info> infos = new List<Info>();
for (int i = 0; i < 10; i++)
{
infos.Add(new Info()
{
Title = $"title {i}",
Text = $"text {i}"
});
}
}
public class Info
{
public string Title { get; set; }
public string Text { get; set; }
}
For example, my List has 100 records, so I need to add 100 StackPanel inside my WrapPanel following the same Title and Text as the List.
Is there any way to do this? For example using Binding?
You would use an ItemsControl that uses a WrapPanel as its ItemsPanel, and defines the layout of the items by an appropriate DataTemplate:
<ItemsControl x:Name="itemsControl">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="120"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding Title}" .../>
<TextBlock Grid.Row="1" Text="{Binding Text}" .../>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
and assign the List<Info> to its ItemsSource property:
itemsControl.ItemsSource = infos;
Related
Im currently trying to use the AdaptiveGrid in the toolkit to display Some images that then can be clicked on to lead to pages, I think this ItemTemplate is what provides the images in the example. Is this the same as any DataTemplate? I cant find any information online about these or docs.
<Controls:AdaptiveGridView Name="AdaptiveGridViewControl"
OneRowModeEnabled="False"
ItemHeight="200"
DesiredWidth="300"
SelectionMode="Single"
IsItemClickEnabled="True"
ItemTemplate="{StaticResource PhotosTemplate}"/>
I've tried the following, I get no errors but nothing shows up when I run it locally except the command bar:
Mainpage.xaml:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MobileAppProject"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="using:ViewModels"
xmlns:Controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
x:Class="MobileAppProject.MainPage"
mc:Ignorable="d">
<Page.Resources>
<DataTemplate x:Key="AdaptTemplate">
<Grid
Background="White"
BorderBrush="Black"
BorderThickness="1">
<Image
Source="{Binding Image}"
Stretch="UniformToFill"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ScrollViewer VerticalScrollMode="Auto" VerticalScrollBarVisibility="Auto">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Margin="12,10,12,12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Margin="0,0,0,10"/>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Controls:AdaptiveGridView Name="AdaptiveGridViewControl"
OneRowModeEnabled="False"
ItemHeight="200"
DesiredWidth="300"
SelectionMode="Single"
IsItemClickEnabled="True"
ItemTemplate="{StaticResource AdaptTemplate}"/>
<StackPanel VerticalAlignment="Bottom" Margin="0,24,0,0" Grid.Row="1" Background="{ThemeResource SystemControlBackgroundAccentBrush}">
<CommandBar x:Name="cmdbar"
IsOpen="{Binding IsChecked, ElementName=isopentoggle, Mode=TwoWay}"
IsSticky="{Binding IsChecked, ElementName=isstickytoggle, Mode=TwoWay}"
ClosedDisplayMode="{Binding SelectedItem.Content, ElementName=combobox}">
<CommandBar.SecondaryCommands>
<AppBarButton Label="Menu Item 1"/>
<AppBarButton Label="Menu Item 2"/>
<AppBarButton Label="Menu Item 3"/>
<AppBarButton Label="Menu Item 4"/>
</CommandBar.SecondaryCommands>
<AppBarButton Icon="Accept" Label="Accept"/>
<AppBarToggleButton Icon="Contact" Label="Contact"/>
</CommandBar>
<Image HorizontalAlignment="Left" Source="Assets/storeLogo-sdk.png" Stretch="None"/>
</StackPanel>
</Grid>
<!-- Status Block for providing messages to the user. Use the
NotifyUser() method to populate the message -->
<TextBlock x:Name="StatusBlock" Grid.Row="2" Margin="12, 10, 12, 10" Visibility="Collapsed"/>
</Grid>
</ScrollViewer>
</Grid>
</Page>
Mainpage.xaml.cs:
private ObservableCollection<AdaptItem> picItems_;
private ObservableCollection<AdaptItem> PicItems
{
get
{
return picItems_;
}
set
{
picItems_ = value;
}
}
public MainPage()
{
this.InitializeComponent();
picItems_ = AdaptItem.AdaptList();
this.DataContext = PicItems;
}
AdaptTemplate.cs for filling the AdaptGrid:
public class AdaptItem
{
public String Image
{
get;
set;
}
}
public static ObservableCollection<AdaptItem> AdaptList()
{
ObservableCollection<AdaptItem> pics = new ObservableCollection<AdaptItem>()
{
new AdaptItem
{
Image = "Assets/01.jpg"
},
new AdaptItem
{
Image = "Assets/02.jpg"
},
new AdaptItem
{
Image = "Assets/03.jpg"
},
new AdaptItem
{
Image = "Assets/04.jpg"
},
new AdaptItem
{
Image = "Assets/05.jpg"
}
};
return pics;
}
You can check how the template is used in the UWP Toolkit sample app or in the sample code on GitHub:
<Controls:AdaptiveGridView Name="AdaptiveGridViewControl"
OneRowModeEnabled="False"
ItemHeight="200"
DesiredWidth="300"
SelectionMode="Single"
IsItemClickEnabled="True"
ItemTemplate="{StaticResource PhotosTemplate}">
<Controls:AdaptiveGridView.Resources>
<DataTemplate x:Key="PhotosTemplate">
<Grid
Background="White"
BorderBrush="Black"
BorderThickness="1">
<Image
Source="{Binding Thumbnail}"
Stretch="UniformToFill"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</Controls:AdaptiveGridView.Resources>
</Controls:AdaptiveGridView>
In short - yes, the ItemTemplate works the same way as any other DataTemplate.
How i can bind observable collection Count value in textblock in windows phone in listbox
<Grid Margin="440,26,10,0" Grid.Row="1" HorizontalAlignment="Right">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,0,0,0">
<Grid Height="25" MinWidth="25">
<Grid.Background>
<ImageBrush ImageSource="{Binding Image}" Stretch="Fill"/>
</Grid.Background>
<TextBlock Name="Message_Count" Text="{Binding CollectionCount}" Foreground="White" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</StackPanel>
</Grid>
List<CountMsg> retrieved = dbConnCount.Table<CountMsg>().ToList<CountMsg>();
dbCount = new ObservableCollection<CountMsg>(retrieved);
i want to bind dbCount.Count in textblock;
Here is an example:
MainWindow.cs:
ObservableCollection<CountMsg> dbCount;
public int CollectionCount
{
get
{
return dbCount.Count;
}
}
public MainWindow()
{
InitializeComponent();
DataContext = this;
List<CountMsg> retrieved = dbConnCount.Table<CountMsg>().ToList<CountMsg>();
dbCount = new ObservableCollection<CountMsg>(retrieved);
}
Xaml:
<Window x:Class="MainWindow">
....
<TextBlock Text="{Binding CollectionCount}" ... />
....
</Window>
I've been working on a control for a while that can be used to repeat a layout in our application. It's working great but the problem is that the controls inside the layout control aren't participating in the logical tree.
It's a custom control with a left header, a right header a body and a standard footer.
Generic.xaml:
<Style TargetType="{x:Type local:FrameControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:FrameControl}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Border VerticalAlignment="Top" Height="50" Background="LightGray"/>
<DockPanel Background="{TemplateBinding HeaderColor}">
<ItemsControl ItemsSource="{TemplateBinding HeaderLeftContent}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel DockPanel.Dock="Left" FlowDirection="LeftToRight" HorizontalAlignment="Left"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<ItemsControl ItemsSource="{TemplateBinding HeaderRightContent}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel DockPanel.Dock="Right" Height="40"
Margin="5, 5, 5, 0" VerticalAlignment="Top"
Orientation="Horizontal" FlowDirection="RightToLeft"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</DockPanel>
<Border BorderThickness="1" BorderBrush="Black" Margin="0,49,0,0" Background="White">
<ItemsControl ItemsSource="{TemplateBinding BodyContent}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<DockPanel Background="White" Margin="5"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Border>
<Border VerticalAlignment="Bottom" Height="0" Background="LightGray"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
FrameControl.cs
public class FrameControl : Control
{
public Brush HeaderColor
{
get { return (Brush)GetValue(HeaderColorProperty); }
set { SetValue(HeaderColorProperty, value); }
}
public static readonly DependencyProperty HeaderColorProperty =
DependencyProperty.Register("HeaderColor", typeof(Brush), typeof(FrameControl), new UIPropertyMetadata(null));
public Collection<Object> HeaderLeftContent
{
get { return (Collection<Object>)GetValue(HeaderLeftContentProperty); }
set { SetValue(HeaderLeftContentProperty, value); }
}
public static readonly DependencyProperty HeaderLeftContentProperty =
DependencyProperty.Register("HeaderLeftContent", typeof(Collection<Object>), typeof(FrameControl),
new UIPropertyMetadata(null));
public Collection<Object> HeaderRightContent
{
get { return (Collection<Object>)GetValue(HeaderRightContentProperty); }
set { SetValue(HeaderRightContentProperty, value); }
}
public static readonly DependencyProperty HeaderRightContentProperty =
DependencyProperty.Register("HeaderRightContent", typeof(Collection<Object>), typeof(FrameControl),
new UIPropertyMetadata(null));
public Collection<Object> BodyContent
{
get { return (Collection<Object>)GetValue(BodyContentProperty); }
set { SetValue(BodyContentProperty, value); }
}
public static readonly DependencyProperty BodyContentProperty =
DependencyProperty.Register("BodyContent", typeof(Collection<Object>), typeof(FrameControl),
new UIPropertyMetadata(null));
static FrameControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(FrameControl), new FrameworkPropertyMetadata(typeof(FrameControl)));
}
public FrameControl()
{
SetValue(HeaderLeftContentProperty, new Collection<Object>());
SetValue(HeaderRightContentProperty, new Collection<Object>());
SetValue(BodyContentProperty, new Collection<Object>());
}
}
Usage example
<fc:FrameControl>
<fc:FrameControl.HeaderLeftContent>
<Label Content="Left content of the header"/>
</fc:FrameControl.HeaderLeftContent>
<fc:FrameControl.HeaderRightContent>
<Button>
<TextBlock Text="Example button"/>
</Button>
<ComboBox SelectedIndex="0">
<ComboBoxItem Content="Filter A"/>
<ComboBoxItem Content="Filter B"/>
<ComboBoxItem Content="Filter C"/>
</ComboBox>
</fc:FrameControl.HeaderRightContent>
<fc:FrameControl.BodyContent>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="name"/>
<TextBox Grid.Row="0" Grid.Column="2"/>
<Label Grid.Row="1" Grid.Column="0" Content="Type name"/>
<TextBox Grid.Row="1" Grid.Column="2" />
<Label Grid.Row="2" Grid.Column="0" Content="Keyword"/>
<TextBox Grid.Row="2" Grid.Column="2"/>
<Label Grid.Row="3" Grid.Column="0" Content="Parameter"/>
<ComboBox Grid.Row="4" Grid.Column="0" SelectedIndex="0">
<ComboBoxItem Content="Width"/>
<ComboBoxItem Content="Height"/>
</ComboBox>
<ComboBox Grid.Row="4" Grid.Column="1" SelectedIndex="0">
<ComboBoxItem Content="..."/>
<ComboBoxItem Content="="/>
<ComboBoxItem Content="<"/>
<ComboBoxItem Content=">"/>
</ComboBox>
<TextBox Grid.Row="4" Grid.Column="2"/>
</Grid>
</fc:FrameControl.BodyContent>
</fc:FrameControl>
I've tried using different type of properties to hold the elements for the different region like UIElementCollection but that made no difference. I also tried manually adding the controls to the logical tree, but I did not succeed in that. Am I missing something?
You say that your actual problem is that you cannot bind using ElementName with this control. Elements that are inside the FrameControl cannot be approached this way. However, that problem has absolutely nothing to do with the visual tree. Those elements are in the visual tree, but you just can't access them because they were defined inside a ControlTemplate.
You can use the ControlTemplate.FindName method to 'find' the elements for you. However, you need to have an element that the ControlTemplate has been applied to and a named element in the ControlTemplate:
// Assuming that your DockPanel in the ControlTemplate was named DockPanel
DockPanel dockPanel =
frameControl.Template.FindName("DockPanel", frameControl) as DockPanel;
if (dockPanel != null) // You must check for null
{
DoSomethingHereWith(dockPanel);
}
See the linked page for more help.
The standard GridApp template is as follows:
Variable Sized Grouped GridView template is as follows:
How to make a template for your application, so that it looks like this:
For example, this design in all applications Bing for windows 8:
Code for Variable Sized Grouped GridView template:
<UserControl.Resources>
<!-- Collection of grouped items displayed by this page -->
<CollectionViewSource
x:Name="groupedItemsViewSource"
Source="{Binding Groups}"
IsSourceGrouped="true"
ItemsPath="Items"
d:Source="{Binding ItemGroups, Source={d:DesignInstance Type=data:SampleDataSource, IsDesignTimeCreatable=True}}"/>
<DataTemplate x:Key="CustomTileItem">
<Grid >
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Image Source="{Binding Image}" Stretch="UniformToFill"/>
</Border>
<StackPanel VerticalAlignment="Bottom" >
<TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextStyle}" Height="30" Margin="15,0,15,0"/>
<TextBlock Text="{Binding Subtitle}" Foreground="{StaticResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
</StackPanel>
</Grid>
</DataTemplate>
</UserControl.Resources>
<!--
This grid acts as a root panel for the page that defines two rows:
* Row 0 contains the back button and page title
* Row 1 contains the rest of the page layout
-->
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Back button and page title -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="backButton" Click="GoBack" IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" Style="{StaticResource BackButtonStyle}"/>
<TextBlock x:Name="pageTitle" Text="{StaticResource AppName}" Grid.Column="1" Style="{StaticResource PageHeaderTextStyle}"/>
</Grid>
<!-- Horizontal scrolling grid used in most view states -->
<ScrollViewer
x:Name="itemGridScrollViewer"
AutomationProperties.AutomationId="ItemGridScrollViewer"
Grid.Row="1"
Margin="0,-3,0,0"
Style="{StaticResource HorizontalScrollViewerStyle}">
<local:MyGridView
x:Name="itemGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Grouped Items"
Margin="116,0,40,46"
ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}"
ItemTemplate="{StaticResource CustomTileItem}"
SelectionMode="None"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick">
<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="75" ItemHeight="150" Orientation="Vertical" Margin="0,0,80,0" MaximumRowsOrColumns="3"/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</local:MyGridView.GroupStyle>
</local:MyGridView>
</ScrollViewer>
and:
public class MyGridView : GridView
{
private int rowVal;
private int colVal;
private Random _rand;
private List<Size> _sequence;
public MyGridView()
{
_rand = new Random();
_sequence = new List<Size> {
LayoutSizes.PrimaryItem,
LayoutSizes.SecondarySmallItem, LayoutSizes.SecondarySmallItem,
LayoutSizes.SecondarySmallItem,
LayoutSizes.SecondaryTallItem,
LayoutSizes.OtherSmallItem, LayoutSizes.OtherSmallItem, LayoutSizes.OtherSmallItem
};
}
protected override void PrepareContainerForItemOverride(Windows.UI.Xaml.DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);
SampleDataItem dataItem = item as SampleDataItem;
int 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(3, 2);
public static Size OtherSmallItem = new Size(2, 1);
}
For example with "Variable Sized Grouped GridView template", we can combine the rows or columns, and how to set the first element height = "auto", and all other elements that have different widths and heights, but grouped as "Variable Sized Grouped GridView template"?
View this post:
http://blogs.msdn.com/b/synergist/archive/2012/09/25/windows-store-app-xaml-gridview-with-variable-templates.aspx
I think this is what you need.
Can someone give me some hints how to accomplish the grouping
within a GridView for Metro Apps as shown in the Screenshot below.
This Screenshot is from the Developer Resources for Windows Metro Apps,
but unfortunately there is no description how to accomplish it.
I have the following code snippet:
Xaml:
...
<Page.Resources>
<CollectionViewSource x:Name="cvs" IsSourceGrouped="true"/>
</Page.Resources>
<Grid Background="{StaticResource DefaultBackground}">
<GridView x:Name="DefaultGridView" ItemsSource="{Binding Source={StaticResource cvs}}">
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="{Binding}" Width="100" Height="100" Margin="0 0 5 0"/>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text='{Binding Key}' Foreground="Gray" Margin="5" FontSize="30" FontFamily="Segoe UI Light" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid MaximumRowsOrColumns="2" Orientation="Horizontal" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</GridView.GroupStyle>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
</Grid>
...
C#:
In the Code-Behind I do the following in the OnNavigateTo Method:
List<string> strList = new List<string>() {
"Red", "Red", "Red", "Red", "Red", "Red",
"Green", "Green","Green","Green","Green",
"Blue","Blue","Blue","Blue" };
var groupedList = from s in strList
group s by s into g
orderby g.Key
select g;
cvs.Source = groupedList;
No matter what I do, I am not able to group the Items in a continues list like in the
Screenshot. The Code results in separate lists grouped side by side.
I may have a solution. In my projet, I had to create a list of contacts in alphabetic order, like the People app.
I used a GridView (with this sample), a CollectionViewSource and a wrappanel I found in the WinRT XAML Toolkit (you can get with NuGet package or copy/paste the source code). It allow you to put your items in columns.
Example
ViewModel
class ContactListViewModel
{
public ContactListViewModel()
{
ContactSource = new CollectionViewSource();
Contacts = new ObservableCollection<Contact>();
Contacts.Add(new Contact("Gates","Bill"));
Contacts.Add(new Contact("Bush","Georges"));
Contacts.Add(new Contact("Obama","Barack"));
Contacts.Add(new Contact("Hollande","François"));
Contacts.Add(new Contact("Affleck","Ben"));
Contacts.Add(new Contact("Allen","Woody"));
Contacts.Add(new Contact("Hendrix","Jimi"));
Contacts.Add(new Contact("Harrison", "Georges"));
Contacts = new ObservableCollection<Contact>(Contacts.OrderBy(c => c.Name));
ContactSource.Source = GetGroupsByLetter();
ContactSource.IsSourceGrouped = true;
}
#region Contacts
public ObservableCollection<Contact> Contacts
{
get;
protected set;
}
public CollectionViewSource ContactSource
{
get;
protected set;
}
#endregion
internal List<GroupInfoList<object>> GetGroupsByLetter()
{
List<GroupInfoList<object>> groups = new List<GroupInfoList<object>>();
var query = from item in Contacts
orderby ((Contact)item).Name
group item by ((Contact)item).Name[0] into g
select new { GroupName = g.Key, Items = g };
foreach (var g in query)
{
GroupInfoList<object> info = new GroupInfoList<object>();
info.Key = g.GroupName;
foreach (var item in g.Items)
{
info.Add(item);
}
groups.Add(info);
}
return groups;
}
public class GroupInfoList<T> : List<object>
{
public object Key { get; set; }
public new IEnumerator<object> GetEnumerator()
{
return (System.Collections.Generic.IEnumerator<object>)base.GetEnumerator();
}
}
}
View
<DataTemplate x:Key="contactTemplate">
<Grid Width="225" Height="75" Background="#55FFFFFF">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" FontSize="20">
<Run Text="{Binding FirstName}"/>
<Run Text="{Binding Name}"/>
</TextBlock>
<TextBlock Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Left" Text="{Binding Email}" FontSize="13" Foreground="#FFDDDDDD"/>
</Grid>
</Grid>
</DataTemplate>
<DataTemplate x:Key="letterTemplate">
<Grid Margin="5,0,0,5" Width="225">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Key}" Style="{StaticResource GroupHeaderTextStyle}" VerticalAlignment="Center"/>
<Rectangle Grid.Row="1" Fill="#BBEEEEEE" Height="1" Margin="0,7,0,0"/>
</Grid>
</DataTemplate>
</Page.Resources>
<!--
This grid acts as a root panel for the page that defines two rows:
* Row 0 contains the back button and page title
* Row 1 contains the rest of the page layout
-->
<Grid Style="{StaticResource LayoutRootStyle}">
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Back button and page title -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="backButton" Click="GoBack" Style="{StaticResource BackButtonStyle}" Opacity="0"/>
<TextBlock x:Name="pageTitle" Grid.Column="1" Text="Manager" Style="{StaticResource PageHeaderTextStyle}"/>
</Grid>
<GridView Grid.Row="1"
ItemsSource="{Binding Path=ContactSource.View}"
SelectionMode="Multiple"
IsSwipeEnabled="false"
IsItemClickEnabled="True"
Padding="116,10,40,46"
ItemTemplate="{StaticResource contactTemplate}">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<local:WrapPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.GroupStyle>
<GroupStyle HeaderTemplate="{StaticResource letterTemplate}">
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical" Margin="0,0,80,0"/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</GridView.GroupStyle>
</GridView>
</Grid>
http://code.msdn.microsoft.com/windowsapps/GroupedGridView-77c59e8e
It can't be done using the default grid view styles.
You may have to use one none-grouped item list and add special items with different item template ...
Sorry
I would add the headers as items to the gridview, and use a TemplateSelector to display the elements the right way...