【问题标题】:Pass value type to Blazor Component将值类型传递给 Blazor 组件
【发布时间】:2023-03-20 08:22:01
【问题描述】:

我正在创建一个类似于DataTables 的 Blazor 组件,并且我还想实现通用过滤器。为此,我为数字创建了 2 个组件:一个整数和另一个浮点数。

从主组件,我想传递数字类型。

<NumberInput TNumber="short"
    Value="@FilterRule.FilterValue"
    OnValueChangedEvent="@FilterRule.UpdateFilterValue"
    IncludeApply="IncludeApply()"
    IsApplied="@FilterRule.IsApplied"
    AppliedText="@FilterRule.FilterValue!.ToString()"
    ApplyFilterEvent="(e) => ApplyFilter(FilterRule.Guid, true)"
    UnApplyFilterEvent="(e) => UnApplyFilter(FilterRule.Guid, true)"
    Attributes="Attributes"
    ApplyButtonCssClass="@ApplyButtonCssClass"
    InputCssClass="@InputCssClass"
    MaxWidth="MaxWidth" />

例如TNumber可以有shortintlong等。这是因为我有一个函数可以为每种类型的数字提供最小值和最大值。

public static Tuple<T, T> GetMinMaxValue<T>()
{
    object obj1 = (object)default(T);
    object obj2 = (object)default(T);

    if (obj1 == null || obj2 == null)
        return (Tuple<T, T>)null;

    switch (Type.GetTypeCode(typeof(T)))
    {
        case TypeCode.Int16:
            obj1 = (object)char.MinValue;
            obj2 = (object)char.MaxValue;
            break;
        case TypeCode.SByte:
            obj1 = (object)sbyte.MinValue;
            obj2 = (object)sbyte.MaxValue;
            break;
        // and so on...
    }
}

NumberInput 有这个代码:

<input class="@DefaultClass form-control-sm @InputCssClass" type="number" value="@Value"
       style="@(MaxWidth != 0 ? string.Format("max-width: {0}px", (object) this.MaxWidth) : "")"
       @onchange="@UpdateValue" step="any">

@code {
    [Parameter] public long Value { get; set; }
    [Parameter] public EventCallback<ValueChangedEventArgs> OnValueChangedEvent { get; set; }
    [Parameter] public string DefaultClass { get; set; } = "form-control";
    [Parameter] public bool IncludeApply { get; set; } = false;
    [Parameter] public bool IsApplied { get; set; } = false;
    [Parameter] public string AppliedText { get; set; } = "";
    [Parameter] public string InputCssClass { get; set; } = "";
    [Parameter] public string ApplyButtonCssClass { get; set; } = "";
    [Parameter] public Dictionary<string, object> Attributes { get; set; }
    [Parameter] public int MaxWidth { get; set; }
    [Parameter] public EventCallback<MouseEventArgs> ApplyFilterEvent { get; set; }
    [Parameter] public EventCallback<MouseEventArgs> UnApplyFilterEvent { get; set; }

    private async Task UpdateValue(ChangeEventArgs args)
    {
        Value = Convert.ToInt32(args.Value.ToString());
        await this.OnValueChangedEvent.InvokeAsync(new ValueChangedEventArgs((object)this.Value));
    }
}

所以,问题是:如何将我想要使用的变量类型作为参数传递?

【问题讨论】:

标签: blazor blazor-server-side blazor-webassembly


【解决方案1】:

@typeparam 指令


正如 Brian Parker 在 cmets 中所暗示的,解决方案是在 NumberInput 组件中添加一个类型参数。在NumberInput 组件中,添加@typeparam Razor 指令:

@typeparam TNumber 

这不过是变相的泛型类型参数。 现在,您可以在 NumberInput 组件中的任何位置使用此参数,就像在 C# 类型(如类或结构)中使用泛型参数一样。 大多数时候,可以推断类型参数的类型,显式设置它们是多余的。但是,如果无法推断类型,则可以显式指定:

<NumberInput 
    TNumber="int"                                       @* Explicitly passing type *@
    Value="@FilterRule.FilterValue"
    OnValueChangedEvent="@FilterRule.UpdateFilterValue"
    IncludeApply="IncludeApply()"
    IsApplied="@FilterRule.IsApplied"
    AppliedText="@FilterRule.FilterValue!.ToString()"
    ApplyFilterEvent="(e) => ApplyFilter(FilterRule.Guid, true)"
    UnApplyFilterEvent="(e) => UnApplyFilter(FilterRule.Guid, true)"
    Attributes="Attributes"
    ApplyButtonCssClass="@ApplyButtonCssClass"
    InputCssClass="@InputCssClass"
    MaxWidth="MaxWidth" />

避免覆盖参数


另外,正如Mister Magoo 所指出的,您不应该覆盖参数值,因为如果容器组件调用StateHasChanged(),子组件的所有参数将被重置为其原始值并且状态将丢失。有关详细信息,请参阅this。为了安全地维护状态,首先将参数值复制到一个私有字段,在OnInitializedOnInitializedAsync

private long _value;
protected override void OnInitialized()
{
        _value = Value;
}

最后的NumberInput


最后,NumberInput 看起来像这样:

@typeparam TNumber

<input class="@DefaultClass form-control-sm @InputCssClass" 
       type="number" 
       value="@Value"
       style="@(MaxWidth != 0 ? string.Format("max-width: {0}px", (object) this.MaxWidth) : "")"
       @onchange="@UpdateValue" 
       step="any" />

@code {

    private long _value;

    [Parameter] public long Value { get; set; }
    [Parameter] public EventCallback<ValueChangedEventArgs> OnValueChangedEvent { get; set; }
    [Parameter] public string DefaultClass { get; set; } = "form-control";
    [Parameter] public bool IncludeApply { get; set; } = false;
    [Parameter] public bool IsApplied { get; set; } = false;
    [Parameter] public string AppliedText { get; set; } = "";
    [Parameter] public string InputCssClass { get; set; } = "";
    [Parameter] public string ApplyButtonCssClass { get; set; } = "";
    [Parameter] public Dictionary<string, object> Attributes { get; set; }
    [Parameter] public int MaxWidth { get; set; }
    [Parameter] public EventCallback<MouseEventArgs> ApplyFilterEvent { get; set; }
    [Parameter] public EventCallback<MouseEventArgs> UnApplyFilterEvent { get; set; }

    private async Task UpdateValue(ChangeEventArgs args)
    {
        _value = Convert.ToInt32(args.Value.ToString());
        await this.OnValueChangedEvent.InvokeAsync(new ValueChangedEventArgs((object)this.Value));
    }

    protected override void OnInitialized()
    {
        _value = Value;
    }
}

【讨论】:

    猜你喜欢
    • 2021-01-18
    • 1970-01-01
    • 2021-01-30
    • 1970-01-01
    • 2021-11-16
    • 1970-01-01
    • 1970-01-01
    • 2021-04-05
    • 1970-01-01
    相关资源
    最近更新 更多