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

Blazor点击按钮隐藏指定表格行(tr)而非全部行的实现问题

问题根因

你定义的IsShow是组件级全局共享变量,foreach循环渲染所有表格行时,每一行的显隐逻辑都读取这同一个值,点击按钮切换该变量时所有行会同步响应,必然出现全显全隐的问题。要实现单行独立控制,必须给每一行维护单独的显隐状态,以下是两种可直接落地的方案。


方案1:在业务模型上增加显隐属性(实现最简单)

如果可以修改part对应的实体类,直接在类上新增行专属的显隐字段,无需额外维护独立状态:

  1. 首先在Part实体类中添加属性,默认值设为显示:
public class Part
{
    // 保留原有所有属性:Part_ID、Part_Number、Part_Description等
    public bool IsRowContentShow { get; set; } = true;
}
  1. 修改表格模板,点击按钮时仅切换当前循环项的属性值,同时用该属性控制行内元素显隐,替换你之前注释掉的按钮代码即可:
<tbody>
    @if (pr_parts != null)
    {
        @foreach (var part in pr_parts)
        {
            {{-- 给tr加@key,避免Blazor渲染时状态串位 --}}
            <tr @key="part.Part_ID" onclick="var s = this.parentNode.querySelector('tr.selected'); s && s.classList.remove('selected'); this.classList.add('selected');">
                <td>@part.Part_ID</td>
                <td>@part.Part_Number</td>
                <td>@part.Part_Description</td>
                <td>@part.Part_Manufacturer</td>
                <td><input for="Stock_Quantity" class="form-control" @bind="@part.Move_Quantity" /></td>
                <td>@part.location</td>
                <td>@to</td>
                <td>
                    <InputSelect id="@($"Shelf_Location_{part.Part_ID}")" @bind-Value="part.Move_Shelf_Location">
                        @if (wip_e == null && wip_o == null)
                        {
                            <option>None Available</option>
                        }
                        else if ((wip_e != null && wip_e.Count() > 0) && (wip_o == null || wip_o.Count() < 1))
                        {
                            <option> </option>
                            @foreach (var shelf in wip_e)
                            {
                                <option value="@shelf.Shelf_Location">@shelf.Shelf_Location</option>
                            }
                        }
                        else if (wip_o != null && wip_o.Count() > 0)
                        {
                            <option> </option>
                            @foreach (var shelf in wip_o)
                            {
                                <option value="@shelf.Shelf_Location">@shelf.Shelf_Location</option>
                            }
                            @foreach (var shelf in wip_e)
                            {
                                <option value="@shelf.Shelf_Location">@shelf.Shelf_Location</option>
                            }
                        }
                    </InputSelect>
                </td>
                @* 用当前行的属性控制元素显隐 *@
                @if (part.IsRowContentShow)
                {
                    <td>@part.category</td>
                    <td><input for="comments" class="form-control" @bind="@part.comments" /></td>
                }
                <td>
                    @if (part.IsRowContentShow)
                    {
                        <button class="btn btn-secondary" @onclick="() => part.IsRowContentShow = false">隐藏</button>
                    }
                    else
                    {
                        <button class="btn btn-secondary" @onclick="() => part.IsRowContentShow = true">显示</button>
                    }
                </td>
            </tr>
        }
    }
</tbody>

注意:@onclick必须用lambda表达式传入当前循环的part对象,直接绑定全局方法会操作到组件级变量。


方案2:用字典独立维护行状态(不适合修改实体时用)

如果不方便修改Part实体类,可以单独创建一个字典存储每行的显隐状态,用Part的唯一标识(比如Part_ID)作为Key:

  1. 在组件的@code块中添加状态字典和切换方法,加载零件数据时初始化默认状态:
@code {
    // 保留原有所有属性:pr_parts、wip_e、wip_o、to等
    private Dictionary<string, bool> _rowStateDict = new();

    protected override void OnInitialized()
    {
        // 初始化所有行默认显示
        if (pr_parts != null)
        {
            foreach (var item in pr_parts)
            {
                _rowStateDict[item.Part_ID] = true;
            }
        }
    }

    private void ToggleRowState(string partId)
    {
        _rowStateDict[partId] = !_rowStateDict[partId];
    }
}
  1. 模板中通过当前行的Part_ID读取字典中的状态,绑定点击事件时传入对应ID即可:
@if (_rowStateDict[part.Part_ID])
{
    <td>@part.category</td>
    <td><input for="comments" class="form-control" @bind="@part.comments" /></td>
}
<td>
    <button class="btn btn-secondary" @onclick="() => ToggleRowState(part.Part_ID)">
        @(_rowStateDict[part.Part_ID] ? "隐藏" : "显示")
    </button>
</td>

避坑提示
  • 循环渲染的元素不要写固定重复的id属性(比如你原来写的id="hide"、id="Shelf_Location"),id是页面全局唯一值,重复id会导致JS选择器、表单关联出错,需要加id时可以拼接唯一主键,比如id=@($"Shelf_Location_{part.Part_ID}")
  • 循环渲染带交互状态的行时,务必给tr标签加@key="唯一标识",Blazor会精准跟踪每个元素的状态,避免滚动、重渲染时出现状态串位的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 11:39:27