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

Blazor中如何传递字符串引用实现原字符串同步编辑?

解决Blazor中字符串属性的双向编辑同步问题

因为C#中字符串是不可变值类型,直接传递字符串会生成副本,无法通过修改副本同步原对象的属性。针对你的场景,提供三种可行方案:


方案1:通过回调传递修改后的值(推荐,符合Blazor设计理念)

利用Blazor的EventCallback实现组件间的双向数据传递,主组件负责更新原Person对象的属性。

修改主组件代码

<div>
  <div @onclick="() => OpenStringEditor(nameof(Person.Name))">@user.Name</div>
  <div @onclick="() => OpenStringEditor(nameof(Person.Surname))">@user.Surname</div>
</div>
<div class="@(ShowEditor ? "ShowEditor" : "HideEditor")">
  <StringEditor ToBeEdited="@_currentEditingValue" EditFinished="@HandleEditFinished" />
</div>

@code {
  [Parameter] public Person user { get; set; } = new Person();
  private bool ShowEditor;
  private string _currentEditingProperty;
  private string _currentEditingValue;

  private void OpenStringEditor(string propertyName)
  {
    _currentEditingProperty = propertyName;
    // 根据属性名获取当前值
    _currentEditingValue = propertyName switch
    {
        nameof(Person.Name) => user.Name,
        nameof(Person.Surname) => user.Surname,
        _ => string.Empty
    };
    ShowEditor = true;
  }

  private void HandleEditFinished(string newValue)
  {
    // 更新Person对应属性
    switch (_currentEditingProperty)
    {
        case nameof(Person.Name):
            user.Name = newValue;
            break;
        case nameof(Person.Surname):
            user.Surname = newValue;
            break;
    }
    user.StoreToDB();
    ShowEditor = false;
  }
}

修改StringEditor组件

<input @bind=ToBeEdited @onfocusout="() => EditFinished.InvokeAsync(ToBeEdited)" />

@code {
  [Parameter] public string ToBeEdited { get; set; } = string.Empty;
  [Parameter] public EventCallback<string> EditFinished { get; set; }
}

方案2:用包装类包裹字符串(模拟引用传递)

将字符串封装到引用类型的包装类中,传递包装类实例即可实现修改同步。

定义StringWrapper包装类

public class StringWrapper
{
    public string Value { get; set; } = string.Empty;
}

修改Person类

public class Person
{
    public StringWrapper Name { get; set; } = new StringWrapper();
    public StringWrapper Surname { get; set; } = new StringWrapper();

    public void StoreToDB()
    {
        // 数据库存储逻辑
    }
}

修改主组件代码

<div>
  <div @onclick="() => OpenStringEditor(user.Name)">@user.Name.Value</div>
  <div @onclick="() => OpenStringEditor(user.Surname)">@user.Surname.Value</div>
</div>
<div class="@(ShowEditor ? "ShowEditor" : "HideEditor")">
  <StringEditor WrapperToEdit="@_stringToEdit" EditFinished="@whenFinished" />
</div>

@code {
  [Parameter] public Person user { get; set; } = new Person();
  private bool ShowEditor;
  private StringWrapper _stringToEdit;

  private void OpenStringEditor(StringWrapper wrapper)
  {
    _stringToEdit = wrapper;
    ShowEditor = true;
  }

  private void whenFinished()
  {
    user.StoreToDB();
    ShowEditor = false;
  }
}

修改StringEditor组件

<input @bind=WrapperToEdit.Value @onfocusout="EditFinished" />

@code {
  [Parameter] public StringWrapper WrapperToEdit { get; set; } = new StringWrapper();
  [Parameter] public EventCallback EditFinished { get; set; }
}

方案3:使用表达式树动态处理属性(适合多属性场景)

通过表达式树动态获取和设置属性,避免大量switch判断,适合Person类有多个字符串属性的场景。

修改主组件代码

<div>
  <div @onclick="() => OpenStringEditor(() => user.Name)">@user.Name</div>
  <div @onclick="() => OpenStringEditor(() => user.Surname)">@user.Surname</div>
</div>
<div class="@(ShowEditor ? "ShowEditor" : "HideEditor")">
  <StringEditor ToBeEdited="@_currentEditingValue" EditFinished="@HandleEditFinished" />
</div>

@code {
  [Parameter] public Person user { get; set; } = new Person();
  private bool ShowEditor;
  private Func<string> _getCurrentValue;
  private Action<string> _setCurrentValue;
  private string _currentEditingValue;

  private void OpenStringEditor(Expression<Func<string>> propertyExpression)
  {
    _getCurrentValue = propertyExpression.Compile();
    _currentEditingValue = _getCurrentValue();
    
    // 解析表达式生成属性赋值逻辑
    var memberExpr = (MemberExpression)propertyExpression.Body;
    var parameter = Expression.Parameter(typeof(string));
    var assignExpr = Expression.Assign(memberExpr, parameter);
    _setCurrentValue = Expression.Lambda<Action<string>>(assignExpr, parameter).Compile();
    
    ShowEditor = true;
  }

  private void HandleEditFinished(string newValue)
  {
    _setCurrentValue(newValue);
    user.StoreToDB();
    ShowEditor = false;
  }
}

StringEditor组件同方案1


方案对比

  • 方案1:最贴合Blazor单向数据流设计,逻辑清晰,维护成本低,推荐优先使用。
  • 方案2:通过包装类模拟引用传递,代码改动稍大,但无需回调逻辑,适合习惯传统引用传递的场景。
  • 方案3:灵活性高,适合属性较多的场景,避免重复代码,但存在轻微的表达式树编译开销(可忽略)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 13:05:19