0

I am trying to create a grid (10 x 10) of red squares. Each square is a <div> element with an @onclick function. When an element is clicked, it should change color to red. I have managed to bind the background of each element to a method, which returns a color, using this code:

@code{
    private string[,] _colors = new string[10,10];

    protected override void OnInitialized() {
        for(int r = 0; r < _colors.GetLength(0); r++) {
            for(int c = 0; c < _colors.GetLength(1); c++) {
                _colors[r, c] = "#FF0000";
            }
        }
    }

    private void ChangeColor(int r, int c) {
        _colors[r,c] = "#0000FF";
    }

    public string GetColor(int r, int c) {
        return _colors[r,c];
    }
}

All pretty basic stuff, which seems to work as intended. However, I am struggling with passing the parameters r and c to ChangeColor as the <div> elements are also generated by code, like this (inspired by this post):

<div class="grid">
@for (int r = 0; r < 10; r++) {
    <div class="row">
    @for (int c = 0; c < 10; c++) {
        <div class="box"><div class="inner" style="background-color: @(GetColor(r,c));" @onclick="() => ChangeColor(r, c)">@((r*10+c).ToString())</div></div>
    }
    </div>
}
</div>

I thought r and c would get the values that they had at the time of generation, but instead they are always 10 (the value they stop at, after the for loops).

Is there any way I can "store" r and c to the element and use it in my onclick event?

Jakob Busk Sørensen
  • 5,599
  • 7
  • 44
  • 96

1 Answers1

1

It's called 'capturing the loop variable', Google that. Lambda's and for-loops don't go so well together.

The quick fix is to make copies:

@for (int r = 0; r < 10; r++) {
    int rr = r;
    <div class="row">
    @for (int c = 0; c < 10; c++) {
        int cc = c;
        <div class="box"><div class="inner" style="background-color: @(GetColor(r,c));" @onclick="() => ChangeColor(rr, cc)">@((r*10+c).ToString())</div></div>
    }
H H
  • 263,252
  • 30
  • 330
  • 514