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

Blazor:如何正确扩展MudButton实现带加载状态的按钮?

问题:封装带加载状态的MudBlazor按钮组件报错解决

我在使用MudBlazor组件库时,需要给表单按钮添加加载状态,官方给出的示例代码如下:

<MudButton Disabled="@_processing" OnClick="ProcessSomething" Variant="Variant.Filled" Color="Color.Primary">
    @if (_processing)
    {
        <MudProgressCircular Class="ms-n1" Size="Size.Small" Indeterminate="true"/>
        <MudText Class="ms-2">Processing</MudText>
    }
    else
    {
        <MudText>Click me</MudText>
    }
</MudButton>

为了复用该加载按钮逻辑,我尝试封装成独立组件,但编写的代码无法正常运行:

@inherits MudButton

@code {
    bool _loading;

    [Parameter]
    public bool Loading 
    {
        get => _loading;
        set
        {
            _loading = value;
            Disabled = value;
        }
    }

    [Parameter]
    public new RenderFragment ChildContent 
    {
        get => base.ChildContent;
        set => base.ChildContent = ExtendContent(value);
    }

    private RenderFragment ExtendContent(RenderFragment baseContent) => __builder =>
    {
        if (Loading)
        {
            <MudProgressCircular Class="ms-n2" Size="Size.Small" Indeterminate="true" />
        }
        @baseContent
    };
}

报错信息:

The type '<my_component>' declares more than one parameter matching the name 'childcontent'. Parameter names are case-insensitive and must be unique.


正确的组件扩展方式

核心问题原因

报错是因为你通过new关键字重新定义了ChildContent参数,而继承的MudButton本身已经存在该参数,Blazor对参数名不区分大小写,导致了参数重复冲突。

推荐实现方案:组合式封装(而非继承重写)

放弃直接继承MudButton,改为将MudButton作为组件内部元素进行组合,这种方式更灵活且避免参数冲突:

<MudButton Disabled="@Loading" @attributes="@AdditionalAttributes" 
           Variant="@Variant" Color="@Color">
    @if (Loading)
    {
        <MudProgressCircular Class="ms-n2" Size="Size.Small" Indeterminate="true" />
        <span class="ms-2">@LoadingText</span>
    }
    else
    {
        @ChildContent
    }
</MudButton>

@code {
    /// <summary>
    /// 是否显示加载状态
    /// </summary>
    [Parameter]
    public bool Loading { get; set; }

    /// <summary>
    /// 加载状态下显示的文本
    /// </summary>
    [Parameter]
    public string LoadingText { get; set; } = "Processing";

    // 按需暴露MudButton常用参数
    [Parameter]
    public Variant Variant { get; set; } = Variant.Filled;

    [Parameter]
    public Color Color { get; set; } = Color.Primary;

    [Parameter]
    public RenderFragment ChildContent { get; set; }

    /// <summary>
    /// 捕获所有未显式定义的参数,自动传递给内部MudButton
    /// </summary>
    [Parameter(CaptureUnmatchedValues = true)]
    public Dictionary<string, object> AdditionalAttributes { get; set; }
}

方案优势

  1. 彻底避免参数冲突问题,逻辑更清晰
  2. 通过AdditionalAttributes可以传递MudButton的所有原生参数(比如OnClick、Class等),无需逐个显式定义
  3. 支持自定义加载文本,扩展性更强

若坚持使用继承方式的修正思路

如果一定要基于继承实现,不能重新定义ChildContent参数,而是通过重写BuildRenderTree方法来修改渲染内容:

@inherits MudButton

@code {
    bool _loading;

    [Parameter]
    public bool Loading 
    {
        get => _loading;
        set
        {
            _loading = value;
            Disabled = value;
            StateHasChanged();
        }
    }

    protected override void BuildRenderTree(RenderTreeBuilder builder)
    {
        builder.OpenComponent<MudButton>(0);
        // 传递MudButton的所有参数
        builder.AddAttribute(1, "Disabled", Disabled);
        builder.AddAttribute(2, "Variant", Variant);
        builder.AddAttribute(3, "Color", Color);
        // 处理点击事件(如果需要保留原生点击逻辑)
        builder.AddAttribute(4, "OnClick", EventCallback.Factory.Create<MouseEventArgs>(this, OnClick));

        // 构建自定义内容
        builder.AddAttribute(5, "ChildContent", (RenderFragment)(__builder =>
        {
            if (Loading)
            {
                __builder.OpenComponent<MudProgressCircular>(6);
                __builder.AddAttribute(7, "Class", "ms-n2");
                __builder.AddAttribute(8, "Size", Size.Small);
                __builder.AddAttribute(9, "Indeterminate", true);
                __builder.CloseComponent();
                __builder.AddContent(10, " ");
                __builder.AddContent(11, LoadingText);
            }
            else
            {
                base.BuildRenderTree(__builder);
            }
        }));

        builder.CloseComponent();
    }

    [Parameter]
    public string LoadingText { get; set; } = "Processing";
}

但这种方式需要手动处理所有参数传递,维护成本较高,推荐优先使用组合式封装方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 17:30:43