Dynamicly create a playboard for Minesweeper game

c#, mvvm, xaml

Solution

You can display your collection using an ItemsControl that has it's `ItemsPanel` set to a `Grid` or `UniformGrid`. I have some `ItemsControl` examples here that may help you, as I don't find MDSN's examples very helpful.

A `UniformGrid` would be easiest if you can bind your `Rows` and `Columns` properties to a property in your `ViewModel`, however that requires all your cells be the same size, and I can't remember if the properties `Rows` and `Columns` are DependencyProperties that participate in the binding system or not.

<ItemsControl ItemsSource="{Binding MyCollection}">
    <!-- ItemsPanelTemplate -->
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Columns="{Binding ColumnCount}" 
                         Rows="{Binding RowCount}" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

If this doesn't work for you, you can use a `Grid` as the `ItemsPanel` and set the `Grid.Row` and `Grid.Column` bindings in the `ItemContainerStyle`.

This will require you have properties on each of your cell objects in the `ObservableCollection` to say what Row/Column that cell is in, however I suspect you'll need these anyways to determine things like adjacent cells in your click command.

In addition, there's no built-in way to bind the number of Rows/Columns in your `Grid`, so I tend to use some custom attached properties that will dynamically build the Grid's `RowDefinitions` and `ColumnDefinitions` based on a bound value.

So your end result if you're using a Grid would probably look something like this:

<ItemsControl ItemsSource="{Binding Cells}">
    <!-- ItemsPanelTemplate -->
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <!-- This is assuming you use the attached properties linked above -->
            <Grid local:GridHelpers.RowCount="{Binding Height}"
                  local:GridHelpers.ColumnCount="{Binding Width}" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <!-- ItemContainerStyle -->
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="Grid.Column" 
                    Value="{Binding ColumnIndex}" />
            <Setter Property="Grid.Row" 
                    Value="{Binding RowIndex}" />
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>

With a Model/ViewModel looking something like this

public class GameViewModel
{
    // These should be full properties w/ property change notification
    // but leaving that out for simplicity right now
    public int Height;
    public int Width;
    public ObservableCollection<CellModel> Cells;
}

public class CellModel
{
    // Same thing, full properties w/ property change notification
    public int ColumnIndex;
    public int RowIndex;
    public bool IsVisible;
    public bool IsMine;
    public int NumberAdjacentMines;
}

Problem

with the objective to learn C#, XAML and especially MVVM I started to program the Minesweeper game. First version I made was without the MVVM part, where I created and added the buttons with C# code instead of doing it in XAML via the MVVM way. Now I try to apply the MVVM pattern into the game. I made an own User Control which contains a button representing a minefield part. This control also has a ViewModel and a Model Class to store some state data and handle some commands. In a test project I create 4 of those own User Controls and try to put them in a grid where the buttons forms a square of 2 by 2 buttons. In the code behind, the buttons are put in an ObservableCollection object. I assume that in this object the buttons are listed and indexed like: ``` Button1 Button2 Button3 Button4 ``` but in the presentation grid I want the buttons to be shown like ``` Button1 | Button2 --------+-------- Button3 | Button4 ``` The question is: how do I do that dynamicly? Cause in my test project I test with 4 buttons, but In the project I want to use this, the amount of buttons can be different depending on the difficulty of the game the player has chosen. And a second question is how I can figure out what the neigbhours are of a button. So if the grid is 4 by 5 containing 20 buttons. And for example I pick button 8 which has as neighbour buttons number 2, 3, 4, 7, 9, 12, 13 and 14. How can I reach those neighbour buttons when the buttons are listed? I hope my questions are clear enough. Thank you in advance!

Original source