I am binding an items control to a datasource and using a grid as my itemshost. I wish to have the items locate themselves into the correct cell in the grid (I can do this), and also stack themselves so they are not all on top of each other (I can't figure out how to insert the items into a stackpanel or other panel in the grid).
here is the .cs file for the two classes:
public class listofdata
{
public List<data> stuff { get; set; }
public listofdata()
{
stuff = new List<data>();
stuff.Add(new data(0, 0, "zeroa"));
stuff.Add(new data(0, 0, "zerob"));
stuff.Add(new data(1, 0, "onea"));
stuff.Add(new data(1, 0, "oneb"));
stuff.Add(new data(1, 1, "twoa"));
stuff.Add(new data(1, 1, "twob"));
}
}
public class data
{
public int x { set; get; }
public int y { set; get; }
public string text { get; set; }
public data(int x, int y, string text)
{
this.x = x;
this.y = y;
this.text = text;
}
}
}
Here is my XAML
<Window x:Class="GridTester.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:GridTester"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" >
<Window.Resources>
<DataTemplate DataType="{x:Type src:data}">
<Button Content="{Binding text}"/>
</DataTemplate>
<src:listofdata x:Key="MyDataSource"> </src:listofdata>
</Window.Resources>
<ListBox Name="Main" ItemsSource="{Binding Source={StaticResource MyDataSource},Path=stuff}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Grid Name="MyGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
</Grid>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style>
<Setter Property="Grid.Column" Value="{Binding x}"/>
<Setter Property="Grid.Row" Value="{Binding y}"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Window>
My problem is that all the buttons ending with 'a' are under the buttons ending in b. I can't see how to use XAML to insert the items into a dynamically created stackpanel
I tried to create a class derived from Grid, thinking to intercept the addition of the children to add stackpanels myself and then move the children from the grid to the stackpanels, but attempting to manipulate the children in an itemshost causes an exception to be thrown.
Ultimately I just want the items in my datasource to be able to bind to a 'cell' in the grid, and if multiple items bind to the same cell, I want them to stack.
You could do this at the data level like HighCore suggested, but since the current data structure already contains the necessary information, it should be possible for the ItemsControl to handle it. Consider adding a group description to the ListBox's item collection, and use a GroupStyle whose Panel is a StackPanel.
Here is the solution using the hints from nmclean (Thanks so much) This section establishes the grouping which will be used to distribute the elements around the grid.
this section is the main listbox bound to the data in the collectionviewsource, The containerstyle contains the bindings to put the groupitem into the correct cells in the grid. The grid is in the groupstyle.panel
Here is the total solution in case you need it:
The code file looks like this now: