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; } }
方案优势
- 彻底避免参数冲突问题,逻辑更清晰
- 通过
AdditionalAttributes可以传递MudButton的所有原生参数(比如OnClick、Class等),无需逐个显式定义 - 支持自定义加载文本,扩展性更强
若坚持使用继承方式的修正思路
如果一定要基于继承实现,不能重新定义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
相关产品推荐
相关产品推荐

