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

Blazor按钮点击处理器无法保留参数值问题求助

问题分析

这是Blazor开发中常见的闭包变量引用捕获问题:你绑定的@onclick lambda表达式()=> {ButtonClicked(i);},捕获的是循环变量i的引用而非每次循环时的具体值。当循环结束后,i的最终值为5(循环条件i<6,最后一次循环后i自增到6才退出),所以所有按钮点击时都会调用ButtonClicked(5)。

解决方案

方法1:循环内创建局部变量保存当前值

在每次循环中,把当前i的值赋值给一个局部变量,让lambda捕获这个局部变量的副本:

@page "/"

<PageTitle>Index</PageTitle>

<div>Number Clicked is  @NumberClicked</div>
<table>
    @for(int i=0; i< 6; i++){
        // 新增局部变量,保存当前循环的i值
        var currentNum = i;
        <tr><td><button type="button" class="btn btn-link" @onclick="()=> {ButtonClicked(currentNum);}">@i</button></td></tr>
    }
</table>

@code {
    public string NumberClicked { get; set; }

    public void ButtonClicked(int i)
    {
        NumberClicked = i.ToString();
    }
}

方法2:改用foreach循环遍历集合

将循环范围转为集合(比如Enumerable.Range(0,6)),foreach循环在C# 5+版本中,每次迭代的变量都是独立实例,lambda会自动捕获当前迭代的变量值:

@page "/"

<PageTitle>Index</PageTitle>

<div>Number Clicked is  @NumberClicked</div>
<table>
    @foreach(var num in Enumerable.Range(0,6)){
        <tr><td><button type="button" class="btn btn-link" @onclick="()=> {ButtonClicked(num);}">@num</button></td></tr>
    }
</table>

@code {
    public string NumberClicked { get; set; }

    public void ButtonClicked(int i)
    {
        NumberClicked = i.ToString();
    }
}
原理补充
  • for循环的变量i是在循环外部声明的,整个循环过程中同一个变量被反复赋值,lambda捕获的是这个变量的内存引用,因此所有按钮最终都会指向变量的最终值。
  • 局部变量currentNum在每次循环时都会生成新的实例,lambda捕获的是当前循环的变量副本,每个按钮对应独立的变量值。
  • foreach循环的迭代变量在C# 5及以后版本中,每次迭代都会创建新的变量实例,天然避免了闭包引用捕获的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 17:01:34