0

我是 blazor 的新手,我遇到了 MudBlazor 组件。这些都很棒,所以我决定在我的项目中实现它们。我想要做的是将我在自己的自定义组件中使用的每个 MudBlazor 组件包装起来,这样如果我将来更改任何内容都会很简单(就像我已经决定从 Radzen 更改为 MudBlazor 的情况一样)。在大多数情况下,这是相当直接的,除了 @bind-Value 属性。我似乎无法弄清楚如何让它工作。这是我包装 MudBlazor“MudTextField”的自定义组件。

<MudTextField @bind-Value="@BindTo" Label="@Label" Variant="@Variant" Margin="@Margin"></MudTextField>

@code {
    private string bindingValue;

    [Parameter]
    public string BindTo
    {
        get => bindingValue;
        set
        {
            if (bindingValue == value) return;
            bindingValue = value;
            BindToChanged.InvokeAsync(value);
        }
    }

    [Parameter] public EventCallback<string> BindToChanged { get; set; }

    [Parameter] public string Label { get; set; }

    [Parameter] public Variant Variant { get; set; } = Variant.Outlined;

    [Parameter] public Margin Margin { get; set; } = Margin.Dense;
}

这是行不通的。当我在调用我的自定义组件时设置 BindTo 参数时,我可以看到 set 属性中的代码被调用,并且 bindingValue 被正确设置,但我绑定到的对象上的属性没有被更新。我需要对 BindToChanged 参数执行其他操作吗?我在研究这个问题时看到另一个例子中使用了它,但我真的不明白它应该做什么。任何帮助,将不胜感激。

谢谢!

4

2 回答 2

1

您需要通过Value,ValueChangedValueExpression进入 MudBlazor 组件。

我不使用 MudBlazor,因此无法正确测试,我只知道如何将其构建为 RenderFragment 而不是在 Razor 中,但这样的东西应该可以工作:

    public class MyMudBlazorTextField<TValue> : ComponentBase
    {
        [Parameter]
        public TValue? Value { get; set; }

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

        [Parameter] public Expression<Func<TValue>>? ValueExpression { get; set; }

        [Parameter] public string Label { get; set; }

        [Parameter] public Variant Variant { get; set; } = Variant.Outlined;

        [Parameter] public Margin Margin { get; set; } = Margin.Dense;

        protected override void BuildRenderTree(RenderTreeBuilder builder)
        {
            builder.OpenComponent<MudTextField<TValue>>(0));
            builder.AddAttribute(1, "Variant", this.Variant);
            builder.AddAttribute(2, "Margin", this.Margin);
            builder.AddAttribute(3, "Label", this.Label);
            builder.AddAttribute(4, "Value", this.Value);
            builder.AddAttribute(5, "ValueChanged", EventCallback.Factory.Create(this, this.ValueChanged));
            builder.CloseComponent();
        }
    }

然后你使用普通的@bind-value

<MyMudBlazorTextField @bind-value=myfield ...../>

你可能白费了很多功夫。诸如 Variant 和 Margin 之类的东西都是 MudBlazor 特有的,而且 MudBlazor 有一些特定的构建方式,所以除非你在你的组件中修复这些,否则你会混淆通用组件的水域(原谅双关语)!

更新

我从AccountMudBlazor Dashboard 项目的页面中提取了一些代码。它使用此函数设置文本字段:

        public static void CreateMudTextField_0<T>(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.String __arg0, int __seq1, global::MudBlazor.Variant __arg1, int __seq2, T __arg2, int __seq3, global::Microsoft.AspNetCore.Components.EventCallback<T> __arg3)
        {
        __builder.OpenComponent<global::MudBlazor.MudTextField<T>>(seq);
        __builder.AddAttribute(__seq0, "Label", __arg0);
        __builder.AddAttribute(__seq1, "Variant", __arg1);
        __builder.AddAttribute(__seq2, "Value", __arg2);
        __builder.AddAttribute(__seq3, "ValueChanged", __arg3);
        __builder.CloseComponent();
        }

基于此,我对代码进行了一些调整。

于 2021-08-03T19:43:36.617 回答
0

我找到了另一种使用 .razor 组件使其工作的解决方案。我本来就很接近。.razor 组件中的代码是正确的。问题是我在调用它时如何传递绑定属性。我很抱歉没有在我的原始请求中包含那部分代码。我不认为这是相关的。

我试图这样称呼它:

<MyInput BindTo=@"MyBindProperty" />

但我需要将它传递给@bind-BindTo

<MyInput @bind-BindTo=@"MyBindProperty" />

MrC aka Shaun Curtis 的答案也以纯 c# 形式出色地工作。

于 2021-08-03T22:21:42.827 回答