使用MVC6标签帮助器的带有用于枚举的单独标签的单选按钮

elo*_*los 5 enums radio-button asp.net-core-mvc tag-helpers

我的模型包含一个我试图绑定到单选按钮列表的枚举,以便在提交表单时只能选择一个值。

public enum Options
{
    [Display(Name="Option A")
    OptionA,
    [Display(Name="Option B")
    OptionB
}

public class MyModel
{
     public Options SelectedOption {get; set;}
     public string TextA{get; set;}
     public string TextB{get; set;}
}
Run Code Online (Sandbox Code Playgroud)

在MVC 5中,我将为每个枚举值呈现一个单选按钮输入,并且用户将只能选择一个。因此,视图中每个单选按钮的代码可能如下所示:

@Html.RadioButtonFor(m => m.SelectedOption, Options.OptionA)
Run Code Online (Sandbox Code Playgroud)

MVC6的问题似乎是输入标签帮助程序不支持现成的枚举属性。因此,如果我尝试添加<input asp-for="SelectedOption"/>,我得到的只是一个文本框。

所以我的问题是,有没有办法使用MVC6标签帮助程序(即开即用或自定义)来完成此操作,还是有另一种方法来执行此操作?也许像使用旧的剃刀语法或仅添加输入标签并填充其属性之类的东西?

请注意,理想情况下,两个单选按钮都必须有标签,以显示枚举[Display]属性中指定的文本。另外,TextATextB文本框只能同时出现,这应该基于所选的单选按钮,但这不在问题的范围内。因此,这就是渲染标记的外观(或多或少):

<div>
    <div>
        <input id="OptionA" type="radio" name="SelectedOption"/>
        <label for="OptionA">Option A</label>
    </div>
    <div>
        <label for="TextA">Text A</label>
        <input type="text" id="TextA" name="TextA">
    </div>
<div>

<div>
<div>
    <input id="OptionB" type="radio" name="SelectedOption"/>
    <label for="OptionB">Option B</label>
</div>

    <div>
        <label for="TextB">Text A</label>
        <input type="text" id="TextB" name="TextB">
    </div>
<div>
Run Code Online (Sandbox Code Playgroud)

diz*_*lus 1

<enum-radio-button asp-for="ThisEnum"></enum-radio-button>
<enum-radio-button asp-for="ThisEnum" value="ThisEnum.Value001"></enum-radio-button>
Run Code Online (Sandbox Code Playgroud)

ThisEnum.Value001 = 自动检查无线电输入..

用于枚举单选按钮列表的 Asp.Net Core TagHelper

/// <summary>
/// <see cref="ITagHelper"/> implementation targeting &lt;enum-radio-button&gt; elements with an <c>asp-for</c> attribute, <c>value</c> attribute.
/// </summary>
[HtmlTargetElement("enum-radio-button", Attributes = RadioButtonEnumForAttributeName)]
public class RadioButtonEnumTagHelper : TagHelper
{
    private const string RadioButtonEnumForAttributeName = "asp-for";
    private const string RadioButtonEnumValueAttributeName = "value";

    /// <summary>
    /// Creates a new <see cref="RadioButtonEnumTagHelper"/>.
    /// </summary>
    /// <param name="generator">The <see cref="IHtmlGenerator"/>.</param>
    public RadioButtonEnumTagHelper(IHtmlGenerator generator)
    {
        Generator = generator;
    }

    /// <inheritdoc />
    public override int Order => -1000;

    [HtmlAttributeNotBound]
    [ViewContext]
    public ViewContext ViewContext { get; set; }

    protected IHtmlGenerator Generator { get; }

    /// <summary>
    /// An expression to be evaluated against the current model.
    /// </summary>
    [HtmlAttributeName(RadioButtonEnumForAttributeName)]
    public ModelExpression For { get; set; }

    [HtmlAttributeName(RadioButtonEnumValueAttributeName)]
    public Enum value { get; set; }

    /// <inheritdoc />
    /// <remarks>Does nothing if <see cref="For"/> is <c>null</c>.</remarks>
    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {

        var childContent = await output.GetChildContentAsync();
        string innerContent = childContent.GetContent();
        output.Content.AppendHtml(innerContent);

        output.TagName = "div";
        output.TagMode = TagMode.StartTagAndEndTag;
        output.Attributes.Add("class", "btn-group btn-group-radio");

        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (output == null)
        {
            throw new ArgumentNullException(nameof(output));
        }

        var modelExplorer = For.ModelExplorer;
        var metaData = For.Metadata;

        if (metaData.EnumNamesAndValues != null)
        {
            foreach (var item in metaData.EnumNamesAndValues)
            {
                string enum_id = $"{metaData.ContainerType.Name}_{metaData.PropertyName}_{item.Key}";

                bool enum_ischecked = false;
                if (value != null)
                {
                    if (value != null && item.Key.ToString() == value.ToString())
                    {
                        enum_ischecked = true;
                    }
                }
                else
                {
                    if (For.Model != null && item.Key.ToString() == For.Model.ToString())
                    {
                        enum_ischecked = true;
                    }
                }

                string enum_input_label_name = item.Key;
                var enum_resourced_name = metaData.EnumGroupedDisplayNamesAndValues.Where(x => x.Value == item.Value).FirstOrDefault();
                if (enum_resourced_name.Value != null)
                {
                    enum_input_label_name = enum_resourced_name.Key.Name;
                }

                var enum_radio = Generator.GenerateRadioButton(
                    ViewContext,
                    For.ModelExplorer,
                    metaData.PropertyName,
                    item.Key,
                    false,
                    htmlAttributes: new { @id = enum_id });
                enum_radio.Attributes.Remove("checked");
                if (enum_ischecked)
                {
                    enum_radio.MergeAttribute("checked", "checked");
                }
                output.Content.AppendHtml(enum_radio);

                var enum_label = Generator.GenerateLabel(
                    ViewContext,
                    For.ModelExplorer,
                    For.Name,
                    enum_input_label_name,
                    htmlAttributes: new { @for = enum_id, @Class = "btn btn-default" });
                output.Content.AppendHtml(enum_label);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在使用这种风格

网页结果