This is a followup for ItemsControl has no children during MainWindow's constructor
Based on the answer to SO question "WPF: arranging collection items in a grid", I have the following:
<ItemsControl Name="itemsControl1" ItemsSource="{Binding MyItems}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid Name="theGrid" ShowGridLines="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type FrameworkElement}">
<Setter Property="Grid.Row" Value="{Binding RowIndex}" />
<Setter Property="Grid.Column" Value="{Binding ColumnIndex}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
Now, I want to set the number of rows and columns of theGrid in the code behind: theGrid.RowDefinitions.Clear(); theGrid.ColumnDefinitions.Clear();
for (uint i = 0; i < theNumberOfRows; i++)
theGrid.RowDefinitions.Add(new RowDefinition());
for (uint i = 0; i < theNumberOfCols; i++)
theGrid.ColumnDefinitions.Add(new ColumnDefinition());
As per MattHamilton's answer there, the gird is available once itemsControl1. ItemContainerGenerator.StatusChanged fires with status of GeneratorStatus.ContainersGenerated.
However, trying to modify the grid from the event handler raises an "Cannot modify 'RowDefinitionCollection' in read-only state" exception.
So, how can I set theGrid's row and column collections before the window is shown to the user?
edit: I'm modifying the Grid's properties from itemsControl1.ItemContainerGenerator.StatusChanged event handler:
if (itemsControl1.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
return;
itemsControl1.ItemContainerGenerator.StatusChanged -= ItemContainerGeneratorStatusChanged;
SetGridRowsAndColumns(InitialNumberOfRows, InitialMaxNumberOfCols);
Notice that SetGridRowsAndColumns(numberOfRows, numberOfCols) does work later, in a response to a button click.
I would use attached behavior as opposed to low level customisation for ItemsControl.
If all you need is a matrix control - you might consider using a row Grid instead of ItemsControl (that's what we've ended up with). ItemsControl is unlimitedly powerful creaturem but some time it can be a challange to squeeze a small but useful extra future through its sound design.
The changes you'll have to make following this approach are: 1. Use Dimension and bind it to to a Size you want it to be. 2. Create a custom ItemTemplate and add GridEx.Position to its root visual bound to the relvant Point property.
On those two, just give us a shout and I'll update my answer with more details.
here's the class:
And here's how we use it: