I want to make something like this
and I can do that by hard coding rectangles into a grid with this code:
<Rectangle Grid.Column="0" Grid.Row="0" Fill="Black" />
<Rectangle Grid.Column="1" Grid.Row="0" Fill="Black" />
<Rectangle Grid.Column="2" Grid.Row="0" Fill="Black" />
<Rectangle Grid.Column="3" Grid.Row="0" Fill="Black" />
<Rectangle Grid.Column="4" Grid.Row="0" Fill="Black" />
However that is just for one line, and if I need different dimensions it can get pretty messy. Is there an easier way of achieving this while still being able to add events to each rectangle?
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With