Reputation: 1436
I have created a nested grid in XAML, which currently looks like this:
<Grid x:Name="mainGrid" >
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid Grid.Row="{Binding Row}" Grid.Column="{Binding Col}">
<Grid.RowDefinitions>
<RowDefinition Height="0.1*"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Title}" VerticalAlignment="Bottom" HorizontalAlignment="Center" Grid.Row="0" FontWeight="Bold" TextDecorations="Underline"/>
<ListView ItemsSource="{Binding Names}" Grid.Row="1"/>
</Grid>
</Grid>
My aim is to populate 4 Grids
that follow the template of the inner Grid
. I have attempted this by using the following code behind:
List<Test> tests = new List<Test>();
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
Test t = new Test();
t.Title = i + "\t" + j;
t.Row = i;
t.Col = j;
tests.Add(t);
}
}
mainGrid.DataContext = tests;
And the class definition:
class Test
{
public string Title { get; set; }
public int Row { get; set; }
public int Col { get; set; }
public ObservableCollection<string> Names
{
get
{
return new ObservableCollection<string>() { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J"};
}
}
}
My thoughts here were that I'd have 4 objects with Row/Col definitions for each segment of the outer Grid
definition (0,0 & 0,1 & 1,0 & 1,1). The inner Grid
would serve as a template like an ItemTemplate
in a ListView
. However only the top (0,0) Grid
is populated.
What steps should I take so that the inner Grid
behaves like a template and all 4 Grids
are created and populated?
Upvotes: 3
Views: 1609
Reputation: 33384
Use ItemsControl
, where ItemsSource
is a list of Test
, and populate ItemsPanel
with outer Grid
and ItemTemplate
with inner Grid
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="Grid.Row" Value="{Binding Row}"/>
<Setter Property="Grid.Column" Value="{Binding Col}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.1*"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Title}" VerticalAlignment="Bottom" HorizontalAlignment="Center" Grid.Row="0" FontWeight="Bold" TextDecorations="Underline"/>
<ListView ItemsSource="{Binding Names}" Grid.Row="1"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
and because ItemsControl
will wrap item in ContentPresenter
you need to move Grid.Column
and Grid.Row
bindings to ItemContainerStyle
EDIT
ItemsControl
is most basic control to display list of something. Controls like ListBox
, ListView
, ComboBox
, DataGrid
and even MenuItem
they all inherit from ItemsControl
adding more functionality on top like selection or column view.
ItemsPanel
defines how the general items' container will look, and ItemTemplate
defines how each item in the collection will look.
Each ItemsControl
will have its item container type. For ListBox
it will be ListBoxItem
, for ListView
it will be ListViewItem
and so on and for ItemsControl
it's ContentPresenter
. It's just a visual container where each item of the list is put as a content, and then - according to hierarchy MSDN: Remarks section - transformed to visual. In the visual tree this container is direct child of the items panel so things list Grid.Column
and/or Grid.Row
must be set against it. Also for example for ListBox
it's ListBoxItem
that holds IsSelected
property. And the way to change that container or get data of the container is via ItemContainerStyle
.
Upvotes: 4