我已经在 Blazor 中定义了一个自定义的select
组件,就像这样:
public class BetterInputSelect<TItem> : InputBase<TItem>
{
[Parameter]
public IEnumerable<TItem> Data { get; set; } = new List<TItem>();
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.OpenElement(0, "select");
builder.AddMultipleAttributes(1, AdditionalAttributes);
builder.AddAttribute(2, "class", CssClass);
builder.AddAttribute(3, "value", BindConverter.FormatValue(CurrentValueAsString));
builder.AddAttribute(4, "onchange", EventCallback.Factory.CreateBinder<string>(
this, value => CurrentValueAsString = value, CurrentValueAsString!, null));
foreach (var item in this.Data)
{
builder.OpenElement(5, "option");
builder.AddAttribute(6, "value", item!.ToString());
builder.AddContent(7, this.FindDisplayName(item));
builder.CloseElement();
}
builder.CloseElement();
}
protected override bool TryParseValueFromString(string? value, out TItem result, out string validationErrorMessage)
{
// Check for enums first.
if (typeof(TItem).IsEnum && BindConverter.TryConvertTo(value, CultureInfo.CurrentCulture, out TItem? parsedValue))
{
result = parsedValue!;
validationErrorMessage = null!;
return true;
}
// Other types here
// ...
result = default!;
validationErrorMessage = $"The {FieldIdentifier.FieldName} field is not valid.";
return false;
}
private string FindDisplayName(TItem value)
{
return value switch
{
null => string.Empty,
Enum @enum => @enum.GetDescription(),
_ => value.ToString() ?? string.Empty
};
}
}
然后可以像这样使用:
<BetterInputSelect Data="@Reasons" @bind-Value="@Reason" />
其中Reasons
和Reason
的定义如下:
public SomeReason Reason { get; set; }
private IEnumerable<SomeReason>? Reasons { get; set; }
...
public enum SomeReason
{
...
}
只要被
@bind-Value
绑定的值不为空,这个方法就能很好地工作。但当我这样做时:public SomeReason? Reason { get; set; }
我遇到了编译时错误:
[CS0411] The type arguments for method
'TypeInference.CreateBetterInputSelect_0<TItem>(RenderTreeBuilder, int, int, IEnumerable<TItem>, int, TItem, int, EventCallback<TItem>, int, Expression<Func<TItem>>)'
cannot be inferred from the usage. Try specifying the type arguments explicitly.
我是否可以不绑定到可空属性,或者有没有办法让编译器满意,我可能错过了什么?
编辑
如果我尝试像这样明确定义类型:
<BetterInputSelect
Data="@Reasons"
@bind-Value="@Reason"
TItem="SomeReason" />
然后我得到以下的编译错误:
[CS1503] Argument 1: cannot convert from 'SomeReason?' to 'SomeReason'
[CS1503] Argument 2: cannot convert from 'Microsoft.AspNetCore.Components.EventCallback<SomeReason?>' to 'Microsoft.AspNetCore.Components.EventCallback'
[CS0266] Cannot implicitly convert type 'SomeReason?' to 'SomeReason'. An explicit conversion exists (are you missing a cast?)
[CS1662] Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type
TItem
属性的类型。 - Panagiotis KanavosTItem="SomeReason"
的东西。 - Kirk WollTItem="SomeReason"
进行了测试。 - Bart Kiers