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

提取Blazor MAUI组件后列表无法更新的问题排查

.NET MAUI Blazor 组件拆分后数据绑定异常问题

我正在尝试用.NET MAUI结合Blazor开发应用,将表格行代码提取为独立组件后遇到了数据绑定问题。

现有Expense类定义

public class Expense
{
    public DateTime Date { get; set; }

    public decimal Amount { get; set; }

    public string Note { get; set; }

    public Expense(DateTime date, decimal amount, string note)
    {
        Date = date;
        Amount = amount;
        Note = note;
    }
}

单组件时功能正常的代码

当所有逻辑都在单个Blazor组件中处理Expense列表时,功能完全正常:

组件HTML部分

<button class="btn btn-primary bg-color-green" @onclick="AddExpense"><i class="oi oi-plus"></i></button>

<table class="table">
    <thead>
        <tr>
            <th>Date</th>
            <th>Amount</th>
            <th>Note</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @for (var i = 0; i < expenses.Count; i++)
        {
            int copy = i;
            <tr>
                <td>
                    <input type="date" min="2022-01-01" max="@currentDay"
                       @bind="@expenses[copy].Date"
                       @bind:format="yyyy-MM-dd" />
                </td>
                <td>
                    <input type="number" min="0" step="0.01" @bind="@expenses[copy].Amount" />
                </td>
                <td>
                    <input type="text" @bind="@(expenses[copy].Note)" />
                </td>
                <td>
                    <button class="btn" @onclick="() => expenses.RemoveAt(copy)"><i class="oi oi-delete"></i></button>
                </td>
            </tr>
        }
    </tbody>
</table>

@code区域代码

private readonly string currentDay = $"{DateTime.Now.Year}-{DateTime.Now.Month}-{DateTime.Now.Day}";

private List<Expense> expenses = new List<Expense>()
{
    new Expense(DateTime.Today, 100, "test")
};

private void AddExpense()
{
    expenses.Add(new Expense(DateTime.Today, 0, ""));
}

拆分后的ExpenseRow组件

将表格行提取为独立的ExpenseRow组件后,出现了问题:

ExpenseRow组件HTML部分

<tr>
    <td>
        <input type="date" min="@MinAttributeValue" max="@MaxAttributeValue"
               @bind="@Date"
               @bind:format="yyyy-MM-dd"/>
    </td>
    <td>
        <input type="number" min="0" step="0.01" @bind="@Amount"/>
    </td>
    <td>
        <input type="text" @bind="@Note"/>
    </td>
    <td>
        <button class="btn" @onclick="() => OnRemoveClick()"><i class="oi oi-delete"></i></button>
    </td>
</tr>

ExpenseRow组件@code区域代码

private string MinAttributeValue => Min.ToString("yyyy-MM-dd");
private string MaxAttributeValue => Max?.ToString("yyyy-MM-dd");

[Parameter]
public DateTime Min { get; set; } = new DateTime(2022, 1, 1);

[Parameter]
public DateTime? Max { get; set; }

[Parameter]
public DateTime Date { get; set; }

[Parameter]
public EventCallback<DateTime> DateChanged { get; set; }

[Parameter]
public decimal Amount { get; set; }

[Parameter]
public EventCallback<decimal> AmountChanged { get; set; }

[Parameter]
public string Note { get; set; }

[Parameter]
public EventCallback<string> NoteChanged { get; set; }

[Parameter]
public Action OnRemoveClick { get; set; }

修改后的原组件代码

原组件更新为在for循环中渲染ExpenseRow组件:

<table class="table">
    <thead>
        <tr>
            <th>Date</th>
            <th>Amount</th>
            <th>Note</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @for (var i = 0; i < expenses.Count; i++)
        {
            int copy = i;
            <ExpenseRow 
                @bind-Amount="expenses[copy].Amount"
                @bind-Date="expenses[copy].Date"
                @bind-Note="expenses[copy].Note"
                Max="@DateTime.Today"
                OnRemoveClick="() => { expenses.RemoveAt(copy); StateHasChanged(); }" />
        }
    </tbody>
</table>

出现的问题

拆分后数据绑定被破坏,存在以下问题:

  • 列表中各项的属性无法更新,切换字段或添加新项后输入的值会被还原;
  • 删除按钮点击后无法移除行,添加StateHasChanged()调用后该问题得到修复;

我尝试在各Changed事件中添加StateHasChanged(),但未解决添加新项时值被还原的问题:

int copy = i;
<ExpenseRow 
    @bind-Amount="expenses[copy].Amount"
    AmountChanged="() => StateHasChanged()"
    @bind-Date="expenses[copy].Date"
    DateChanged="() => StateHasChanged()"
    @bind-Note="expenses[copy].Note"
    NoteChanged="() => StateHasChanged()"
    Max="@DateTime.Today"
    OnRemoveClick="() => { expenses.RemoveAt(copy); StateHasChanged(); }" />

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 20:39:15