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

通过委托访问值类型:Blazor组件数据更新失效问题

问题分析与解决方案

核心问题

你当前代码无法修改底层数据的原因是:itemEdited委托返回的是值类型(decimal)的副本。值类型在传递时按值复制,你对itemEd的赋值操作只会修改这个副本,完全不会影响原AtomicMetric对象的JobValue属性。

解决方案

把负责属性选择的Func<TEdit, Object>委托,替换成能直接修改属性的Action<TEdit, object>委托(或更类型安全的泛型版本),让委托内部直接完成属性赋值操作,而非返回值类型副本。

步骤1:修改事件处理方法

将HandleEvent的第三个参数从Func<TEdit, Object>改为Action<TEdit, object>,直接调用委托完成赋值:

private void HandleEvent(List<TEdit> editItems, Func<List<TEdit>, TEdit> itemEditedFilter, Action<TEdit, object> itemSetter)
{
    var itemToChange = itemEditedFilter(editItems);
    if (itemToChange == null) return; // 增加空值判断,避免空引用异常
    
    // 直接调用委托修改原对象的属性
    itemSetter(itemToChange, editedValue);
}

步骤2:更新委托定义

在Blazor组件中,把ItemEdited的委托改成直接赋值的逻辑,而非返回属性值:

ItemEdited="@((PeriodicMetricDTO x, object newValue) => x.cf.JobValue = Convert.ToDecimal(newValue))"

(可选)类型安全优化版本

如果想避免装箱拆箱和类型转换的潜在问题,可以使用带泛型参数的版本:

private void HandleEvent<TProperty>(List<TEdit> editItems, Func<List<TEdit>, TEdit> itemEditedFilter, Action<TEdit, TProperty> itemSetter)
{
    var itemToChange = itemEditedFilter(editItems);
    if (itemToChange == null) return;
    
    // 类型检查确保转换安全
    if (editedValue is TProperty newValue)
    {
        itemSetter(itemToChange, newValue);
    }
}

对应的委托定义更简洁:

ItemEdited="@((PeriodicMetricDTO x, decimal newValue) => x.cf.JobValue = newValue)"

原理说明

AtomicMetric是引用类型,x.cf指向堆上的实际对象。通过Action委托直接访问x.cf.JobValue并赋值,本质是对堆上对象的属性进行修改,因此会直接同步到底层数据集。而原来的Func返回值类型时,只是把值复制出来,修改副本不会影响原对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 06:13:30