将值类型传递给Blazor组件



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

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

<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));
}
}

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

@typeparam指令


正如Brian Parker在评论中暗示的那样,解决方案是向NumberInput组件添加一个类型参数。在NumberInput组件中,添加@typeparamRazor指令:

@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(),则子组件的所有参数都将重置为其原始值,并且状态将丢失。有关更多信息,请参阅此。为了安全地维护状态,请先将参数值复制到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;
}
}

相关内容

  • 没有找到相关文章

最新更新