It is a bit tricky to bind a runtime-variable number of items to a Grid. One option is to use an ItemsControl, with a Grid as the ItemsPanel.
You would have a 2-dimensional array in the view-model, with each cell containing its row and column numbers. Use the ItemContainerStyle to bind the container's Grid.Row and Grid.Column attached properties to the cell view-model properties.
<ItemsControl ItemsSource="{Binding Cells}"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <Grid /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemContainerStyle> <Style TargetType="ContentPresenter"> <Setter Property="Grid.Row" Value="{Binding RowNumber}" /> <Setter Property="Grid.Column" Value="{Binding ColumnNumber}" /> </Style> </ItemsControl.ItemContainerStyle> <ItemsControl.ItemTemplate> <DataTemplate> <Rectangle Fill="Black" /> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
The piece that needs to be added to the above is adding the row/column definitions to the Grid. For this I would use attached properties that add those definitions for you, allowing you to bind the definitions to a property in your view model. That way, you can write something like:
<ItemsPanelTemplate> <Grid GridHelpers.RowCount="{Binding RowCount}" GridHelpers.ColumnCount="{Binding ColumnCount}" /> </ItemsPanelTemplate>
Finally, for the events, you can use an EventTrigger along with an InvokeCommandAction to trigger an ICommand on any event of the Rectangles.
<DataTemplate> <Rectangle> <i:Interaction.Triggers> <i:EventTrigger EventName="MouseDoubleClick"> <i:InvokeCommandAction Command="{Binding RectangleClickCommand}" CommandParameter="{Binding}" /> </i:EventTrigger> </i:Interaction.Triggers> </Rectangle> </DataTemplate>