You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor中@oninput绑定循环索引越界问题求助

问题原因

这是Blazor中闭包捕获循环变量的典型问题:@for循环里的row和col是循环体外声明的变量,lambda表达式@(e => {this.updateDogSpeed(row, col, e);})捕获的是变量本身,而非循环迭代时的当前值。当循环结束后,row和col都会递增到dogList.Count(也就是8),所以任何输入框触发事件时,拿到的都是这两个变量的最终值。

解决方案(两种规范的Blazor原生写法)

方法一:循环内创建局部变量捕获当前值

在@for循环内部,为每一次迭代创建独立的局部变量,让lambda捕获这些局部变量的当前值:

<table class="table">
    <thead>
        <!--
        <tr>
            <th>Runs with</th>
            @foreach (var dog in dogList)
            {
                <th>@dog.name</th>
            }
        </tr>
        -->
    </thead>
    <tbody>
        <tr>
            <td style="width:120px;">Runs with ↗️ </td>
            @foreach(Dog dog in dogList)
            {
                <td style="width:120px;">@dog.name</td>
            }
        </tr>
        @for(var row = 0; row<dogList.Count; row++)
        {
            // 声明局部变量保存当前row值
            var currentRow = row;
            <tr>
                <td style="width:120px;">@dogList[row].name</td>
                @for (var col = 0; col<dogList.Count; col++)
                {
                    // 声明局部变量保存当前col值
                    var currentCol = col;
                    <td style="width:120px;">
                        <input type="number" 
                            value="@dogSpeed[currentRow][currentCol]"
                            @oninput="@(e => updateDogSpeed(currentRow, currentCol, e))"
                        />
                    </td>
                }
            </tr>
        }
    </tbody>
</table>

@code {
    public void updateDogSpeed(int row, int col, ChangeEventArgs e)
    {
        if(double.TryParse(e.Value?.ToString(), out var newValue))
        {
            dogSpeed[row][col] = newValue;
            // 可选:若UI未自动更新,手动触发状态变更
            // StateHasChanged();
        }
        Console.WriteLine($"row={row}, col={col}, e.Value={e.Value}");
    }
}

方法二:改用@foreach结合索引遍历

通过Select给每个元素绑定索引,彻底避免@for的闭包问题:

<table class="table">
    <thead>
        <!--
        <tr>
            <th>Runs with</th>
            @foreach (var dog in dogList)
            {
                <th>@dog.name</th>
            }
        </tr>
        -->
    </thead>
    <tbody>
        <tr>
            <td style="width:120px;">Runs with ↗️ </td>
            @foreach(Dog dog in dogList)
            {
                <td style="width:120px;">@dog.name</td>
            }
        </tr>
        @foreach(var rowItem in dogList.Select((dog, index) => new { Dog = dog, Row = index }))
        {
            <tr>
                <td style="width:120px;">@rowItem.Dog.name</td>
                @foreach(var colItem in dogList.Select((dog, index) => new { Dog = dog, Col = index }))
                {
                    <td style="width:120px;">
                        <input type="number" 
                            value="@dogSpeed[rowItem.Row][colItem.Col]"
                            @oninput="@(e => updateDogSpeed(rowItem.Row, colItem.Col, e))"
                        />
                    </td>
                }
            </tr>
        }
    </tbody>
</table>

@code {
    public void updateDogSpeed(int row, int col, ChangeEventArgs e)
    {
        if(double.TryParse(e.Value?.ToString(), out var newValue))
        {
            dogSpeed[row][col] = newValue;
        }
        Console.WriteLine($"row={row}, col={col}, e.Value={e.Value}");
    }
}
补充说明
  • 两种方法都无需JavaScript,完全遵循Blazor原生规范。
  • 用double.TryParse做安全转换,避免输入非数字导致程序报错。
  • 若修改数组后UI未自动更新,可手动调用StateHasChanged()(比如当dogSpeed是值类型二维数组时,Blazor可能无法检测到内部元素变化)。

内容的提问来源于stack exchange,提问作者TomEberhard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 11:42:58