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

Blazor中列表内下拉选择与模型项绑定问题求助

解决方案:Blazor费用列表分类绑定问题

核心问题分析

你的代码存在几个关键问题导致绑定失效:

  • @foreach循环未使用@key标识列表项,Blazor无法正确追踪每个Expense实例的状态
  • 所有下拉框使用相同的id属性,DOM中重复id会导致绑定逻辑混乱
  • OnChangeCategory事件未关联当前操作的Expense项,全局更新子分类列表无法对应到单个费用项
  • 错误使用旧版bind语法(正确应为@bind),分类下拉框仅用value而非双向绑定

修正后的前端代码

<EditForm Model="@expenses">
    <table>
        @foreach (Expense expense in expenses)
        {
            <!-- 使用@key确保Blazor正确追踪每个列表项 -->
            <tr @key="expense.Key">
                <td>@expense.Key</td>
                <td>@expense.Date</td>
                <td>@expense.Item</td>
                <td>@expense.Cost</td>
                <td>
                    <!-- 双向绑定到当前expense的分类名称,同时传递当前expense到事件 -->
                    <select @bind="expense.Category.Name" 
                            @onchange="(e) => OnChangeCategory(e, expense)"
                            id="@($"category-{expense.Key}")">
                        <option value="">Choose Category</option>
                        @foreach (Category category in categories)
                        {
                            <option value="@category.Name">@category.Name</option>
                        }
                    </select>
                </td>
                <td>
                    <!-- 绑定到当前expense的子分类列表和选中项 -->
                    <select @bind="expense.Category.SelectedSubCategory"
                            id="@($"subcategory-{expense.Key}")">
                        <option value="">Choose SubCategory</option>
                        @foreach (string subCategory in expense.Category.SubCategories)
                        {
                            <option value="@subCategory">@subCategory</option>
                        }
                    </select>
                </td>
            </tr>
        }
    </table>
    <button @onclick="SaveExpenses">Save Expenses</button>
</EditForm>

修正后的后端代码

@code {
    public List<Expense> expenses = new List<Expense>();
    public List<Category> categories = new List<Category>(); // 假设已初始化

    // 接收ChangeEventArgs和当前操作的Expense实例
    private void OnChangeCategory(ChangeEventArgs e, Expense currentExpense)
    {
        var selectedCategory = categories.FirstOrDefault(c => c.Name == e.Value.ToString());
        if (selectedCategory != null)
        {
            // 更新当前expense的子分类列表,而非全局列表
            currentExpense.Category.SubCategories = selectedCategory.SubCategories;
            // 清空当前expense的子分类选中项,避免无效值
            currentExpense.Category.SelectedSubCategory = string.Empty;
        }
        else
        {
            currentExpense.Category.SubCategories = new List<string>();
        }
    }

    private void SaveExpenses()
    {
        // 处理保存逻辑,此时expenses列表已包含所有选中的分类和子分类
    }
}

关键修改说明

  1. @key的使用:在<tr>上添加@key="expense.Key",让Blazor能精准识别每个列表项的状态变化,避免渲染混乱
  2. 动态ID:用@($"category-{expense.Key}")生成唯一ID,解决DOM重复ID问题
  3. 双向绑定与事件关联:分类下拉框用@bind实现双向绑定,同时通过lambda表达式传递当前Expense到OnChangeCategory,确保只更新当前项的子分类
  4. 子分类本地化:将子分类列表绑定到当前Expense的Category.SubCategories,每个费用项拥有独立的子分类选项集合,避免全局更新影响所有项
  5. 简化逻辑:用FirstOrDefault替代循环查找分类,提升代码效率

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 12:16:04