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

MudRating点击时SelectedValueChanged触发两次问题排查与解决

MudRating二次触发SelectedValueChanged的问题分析与解决

问题场景

采用三层结构开发:

  • 主Razor文件:
<Rating @bind-Value="@Model.RoiRating" Descriptions="@Rating.RoiDescriptions"/>
  • Rating.razor:
<MudRating SelectedValue="Value" SelectedValueChanged="OnSelectedValueChanged" HoveredValueChanged="OnHoveredValueChanged" />
<MudText Typo="Typo.subtitle2" Class="deep-purple-text mt-2">@RatingText</MudText>
  • Rating.razor.cs:
public partial class Rating
{
    public static string[] RoiDescriptions = new[]
    {
        "Rate the ROI",
        "Damaging",
        "Negative",
        "Ineffective",
        "Helpful",
        "Awesome!"
    };

    [Parameter]
    public string[] Descriptions { get; set; } = RoiDescriptions;

    [Parameter]
    public int Value { get; set; }

    [Parameter]
    public EventCallback<int> ValueChanged { get; set; }

    private int? _activeValue;

    private void OnHoveredValueChanged(int? val) => _activeValue = val;

    private string RatingText
    {
        get
        {
            if (_activeValue is null or < 1 or > 5)
                return Descriptions[0];
            return Descriptions[_activeValue.Value];
        }
    }
}

点击第3颗星时,调试器显示两次调用:

OnSelectedValueChanged(3)
OnSelectedValueChanged(0)

问题原因

  1. Rating组件未实现OnSelectedValueChanged方法,无法将MudRating的新值同步到上层绑定的Value参数。
  2. 当MudRating触发SelectedValueChanged(3)后,组件因状态变化重新渲染,但上层的Model.RoiRating(即Rating组件的Value参数)仍为原始值(比如0)。
  3. 重新渲染时,MudRating的SelectedValue被重置为Value的原始值0,因此再次触发SelectedValueChanged(0)。

解决方法

核心是通过内部状态同步值,并正确触发ValueChanged回调更新上层绑定数据,同时遵循Blazor参数不可直接修改的规则。

修改后的Rating.razor.cs

public partial class Rating
{
    public static string[] RoiDescriptions = new[]
    {
        "Rate the ROI",
        "Damaging",
        "Negative",
        "Ineffective",
        "Helpful",
        "Awesome!"
    };

    [Parameter]
    public string[] Descriptions { get; set; } = RoiDescriptions;

    [Parameter]
    public int Value { get; set; }

    [Parameter]
    public EventCallback<int> ValueChanged { get; set; }

    private int? _activeValue;

    // 初始化时同步上层Value到内部状态
    protected override void OnInitialized()
    {
        _activeValue = Value;
    }

    // 上层参数更新时同步内部状态
    protected override void OnParametersSet()
    {
        if (_activeValue != Value)
        {
            _activeValue = Value;
        }
    }

    // 处理MudRating的值变化
    private async Task OnSelectedValueChanged(int val)
    {
        _activeValue = val;
        // 通知上层更新绑定数据
        await ValueChanged.InvokeAsync(val);
    }

    private void OnHoveredValueChanged(int? val) => _activeValue = val;

    private string RatingText
    {
        get
        {
            if (_activeValue is null or < 1 or > 5)
                return Descriptions[0];
            return Descriptions[_activeValue.Value];
        }
    }
}

修改后的Rating.razor

<MudRating SelectedValue="@_activeValue" 
           SelectedValueChanged="OnSelectedValueChanged" 
           HoveredValueChanged="OnHoveredValueChanged" />
<MudText Typo="Typo.subtitle2" Class="deep-purple-text mt-2">@RatingText</MudText>

修改说明

  • 用内部私有字段_activeValue维护组件的当前选中状态,避免直接依赖不可修改的Value参数。
  • 通过OnInitialized和OnParametersSet同步上层传入的Value到内部状态,保证初始值和参数更新时的一致性。
  • 实现OnSelectedValueChanged方法,在MudRating值变化时,先更新内部状态,再通过ValueChanged回调通知上层更新绑定的Model.RoiRating,确保组件重新渲染时Value参数为新值,不会重置MudRating的选中状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 12:16:03