在 Blazor 中使用 Input radio 并允许可为 null 的 Enum

Using Input radio inside Blazor and allowing nullable Enum

我在 Blazor WebAssembly 项目上工作,我需要显示基于 Enum 的输入单选按钮。

下面是我的'InputRadio.razor'

    @using System.Globalization
    @typeparam TValue
    @inherits InputBase<TValue>

    <input @attributes="AdditionalAttributes" type="radio" value="@SelectedValue" checked="@(SelectedValue.Equals(Value))" @onchange="OnChange" />

    @code {
        [Parameter]
        public TValue SelectedValue { get; set; }
        [Parameter]
        public EventCallback<ChangeEventArgs> SelectedValueChanged { get; set; }

        private void OnChange(ChangeEventArgs args)
        {
            if (args.Value is "on") {            // <------- only way to test if value is null. Why "on" ??? 
                CurrentValueAsString = null;
            } else {
                CurrentValueAsString = args.Value.ToString();
            }
            SelectedValueChanged.InvokeAsync(args);
        }

        protected override bool TryParseValueFromString(string value, out TValue result, out string errorMessage)
        {
            var success = BindConverter.TryConvertTo<TValue>(value, CultureInfo.CurrentCulture, out var parsedValue);
            if (success)
            {
                result = parsedValue;
                errorMessage = null;

                return true;
            }
            else
            {
                result = default;
                errorMessage = $"{FieldIdentifier.FieldName} field isn't valid.";

                return false;
            }
        }
    }

下面是我的'Test.razor'

<EditForm Model="CurrentFilterModel">
<InputRadio name="difficulty" SelectedValue="null"                        SelectedValueChanged="FilterCourses" @bind-Value="@CurrentFilterModel.DifficultyFilter" /> All
<InputRadio name="difficulty" SelectedValue="EnumDifficulty.Beginner"     SelectedValueChanged="FilterCourses" @bind-Value="@CurrentFilterModel.DifficultyFilter" /> Beginner
<InputRadio name="difficulty" SelectedValue="EnumDifficulty.Intermediate" SelectedValueChanged="FilterCourses" @bind-Value="@CurrentFilterModel.DifficultyFilter" /> Intermediate
<InputRadio name="difficulty" SelectedValue="EnumDifficulty.Advanced"     SelectedValueChanged="FilterCourses" @bind-Value="@CurrentFilterModel.DifficultyFilter" /> Advanced
</EditForm>

低于'Test.cs'

public enum EnumDifficulty
{
    Beginner,
    Intermediate,
    Advanced
}

public FilterModel CurrentFilterModel = new FilterModel();

public class FilterModel
{
   public EnumDifficulty? DifficultyFilter { get; set; }
   ...
}

如您所见,使用的 DifficultyFilter 过滤器可以为空。当 null 我知道这个过滤器没有设置。

这个实现有效。每次选择单选按钮时,都会触发 onchange 事件。我很难处理 null 值。在搜索和尝试之后,我发现测试 if (args.Value is "on") ... 允许我管理 null 值。但是为什么 "on" 呢?我没有线索。请看看我上面的代码。

有些人可能会建议我这样调整 Enum

public enum EnumDifficulty
{
    Any,     // <--- added 
    Beginner,
    Intermediate,
    Advanced
}

但我不想这样,因为这个枚举也用在我的 Entity Framework 模型上,这不是一个有效的选择。

** 更新 **

下面是 TryParseValueFromString

的完整代码
protected override bool TryParseValueFromString(string value, out TValue result, out string errorMessage)
{
    if (typeof(TValue) == typeof(string))
    {
        result = (TValue)(object)value;
        errorMessage = null;
        return true;
    }
    else if (typeof(TValue).IsNullableEnum()) // (typeof(TValue).IsEnum) 
    {
        var success = BindConverter.TryConvertTo<TValue>(value, CultureInfo.CurrentCulture, out var parsedValue);
        if (success)
        {
            result = parsedValue;
            errorMessage = null;
            return true;
        }
        else
        {
            result = default;
            errorMessage = $"The {FieldIdentifier.FieldName} field is not valid.";
            return false;
        }
    }
    if (typeof(TValue) == typeof(int))
    {
        if (int.TryParse(value, out var resultInt))
        {
            result = (TValue)(object)resultInt;
            errorMessage = null;
            return true;
        }
        else
        {
            result = default;
            errorMessage = "The chosen value is not a valid number.";
            return false;
        }
    }

    throw new InvalidOperationException($"{GetType()} does not support the type '{typeof(TValue)}'.");
}

public static class CustomStaticFunctions
{
    public static bool IsNullableEnum(this Type t)
    {
        Type u = Nullable.GetUnderlyingType(t);
        return (u != null) && u.IsEnum;
    }
}

不确定你的问题是什么!?你想知道什么 ?什么是 "on?"

"on"是选中单选框的value属性时赋给单选组的值 单选按钮丢失。这是我以前的认识。我的新知识(希望我是对的)来自你,这意味着 value 属性不一定会丢失以导致值 "on" ... value 属性为空(可能为空或为空)就足够了string) 给我们值 "on".

您确定您的组件正常工作吗?您的代码缺少检查枚举值的这一部分:

   else if (typeof(TValue).IsEnum) 
    {
        var success = BindConverter.TryConvertTo<TValue>(value, CultureInfo.CurrentCulture, out var parsedValue);
        if (success)
        {
            result = parsedValue;
            validationErrorMessage = null;
            return true;
        }
        else
        {
            result = default;
            validationErrorMessage = $"The {FieldIdentifier.FieldName} field is not valid.";
            return false;
        }
    }