Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a grid filled with rectangles

Tags:

c#

wpf

xaml

I want to make something like this

ing1

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?

like image 512
RidableCthulu Avatar asked Oct 20 '22 04:10

RidableCthulu


1 Answers

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>

like image 103
McGarnagle Avatar answered Oct 27 '22 10:10

McGarnagle