ASP.NET 5 MVC 6 中的单选按钮标记帮助程序

Posted

技术标签:

【中文标题】ASP.NET 5 MVC 6 中的单选按钮标记帮助程序【英文标题】:Radio Button Tag Helpers in ASP.NET 5 MVC 6 【发布时间】:2016-01-02 21:26:52 【问题描述】:

我在 ASP.NET 5 MVC 6 中没有看到任何单选按钮的标签助手。在我需要使用单选按钮的情况下,处理表单元素的正确方法是什么?

【问题讨论】:

【参考方案1】:

所有输入类型都有一个 TagHelper,其中也包括单选按钮类型。假设你有这样的视图模型

public class CreateUserVm

    public string UserName  set; get; 
    public IEnumerable<RoleVm> Roles  set; get;  
    public int SelectedRole  set; get; 

public class RoleVm

    public int Id  set; get; 
    public string RoleName  set; get;         

在您的 GET 操作中,

public IActionResult Index()

    var vm = new CreateUserVm
    
        Roles = new List<RoleVm>
        
            new RoleVm Id = 1, RoleName = "Admin",
            new RoleVm Id = 2, RoleName = "Editor",
            new RoleVm Id = 3, RoleName = "Reader"
        
    ;
    return View(vm);

在视图中,您可以简单地对输入标签使用标记。

@model YourNamespaceHere.CreateUserVm
<form asp-action="Index" asp-controller="Home">
    <label class="label">User name</label>
    <div class="col-md-10">
        <input type="text" asp-for="UserName" />
    </div>
    <label class="label">Select a Role</label>
    <div class="col-md-10">
    @foreach (var item in Model.Roles)
    
       <input asp-for="SelectedRole" type="radio" value="@item.Id" /> @item.RoleName
    
    </div>
    <input type="submit" />
</form>

当您发布表单时,所选角色的 Rold Id 将位于 SelectedRole 属性中

请记住,上面的 razor 代码将为循环生成的每个输入生成具有 same Id 属性值和 name 属性值的输入元素。在上面的示例中,它将生成 3 个输入元素(单选按钮类型),其中 Idname 属性值设置为 SelectedRole。当name 属性值与我们的视图模型中的属性名称(SelectedRole)匹配时,模型绑定将起作用,但重复的 Id 属性值可能会给您带来客户端代码的麻烦(文档中的重复 Ids 无效)

【讨论】:

我在单选按钮上使用 JS 点击事件来提交表单,但是单选按钮的值永远不会传递给我的操作方法。我是否必须将无线电输入上的名称或 id 属性设置为特定的东西? 问题:我可以将值设置为真还是假? value="true"? 如果这是您在选择单选按钮时想要传递的内容 这不会在浏览器控制台中产生错误吗?和我一样,ASP.Net 核心(我认为)为每个无线电输入生成相同的 Id。 显然现在的解决方法是手动设置id html 属性以覆盖标签助手行为。【参考方案2】:

虽然有使用asp-for="SomeField" 的解决方案,但我发现最简单的解决方案是将视图模型字段与单选按钮的name 字段匹配。

查看模型:

public class MyViewModel

   public string MyRadioField  get; set; 

表格(为清楚起见没有标签):

@model MyViewModel
<form asp-action="SomeAction" asp-controller="SomeController">
   <input type="radio" name="MyRadioField" value="option1" checked />
   <input type="radio" name="MyRadioField" value="option2" />
   <input type="radio" name="MyRadioField" value="option3" />

   <input type="submit" />
</form>

提交表单后,MyRadioField 将填充选中单选按钮的值。

【讨论】:

【参考方案3】:

我已经编写了自己的标签助手来做到这一点。它用每个枚举变量的标签和单选按钮替换 input 标签:

using System.Collections.Generic;
using System.Linq;
using System.Text;
using DigitScpi.Web.Helpers;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;

namespace TagHelpers

    /// Generates the radio buttons for an enum. Syntax: `<input radio asp-for="MyMappedEnumField"/>`.
    [HtmlTargetElement("input", Attributes = RadioAttributeName)]
    public class RadioButtonTagHelper : TagHelper
    
        private const string RadioAttributeName = "radio";
        private const string ForAttributeName = "asp-for";

        [HtmlAttributeNotBound] [ViewContext] public ViewContext ViewContext  get; set; 
        private readonly IHtmlGenerator _generator;

        [HtmlAttributeName(ForAttributeName)] public ModelExpression For  get; set; 
        [HtmlAttributeName(RadioAttributeName)] public bool RadioMarker  get; set; 

        public RadioButtonTagHelper(IHtmlGenerator generator)
        
            _generator = generator;
        

        /// <inheritdoc />
        public override void Process(TagHelperContext context, TagHelperOutput output)
        
            output.SuppressOutput();

            foreach (var enumItem in For.Metadata.EnumNamesAndValues)
            
                var id = VariantId(enumItem);
                var name = For.Metadata.EnumGroupedDisplayNamesAndValues.FirstOrDefault(v => v.Value == enumItem.Value).Key.Name;
                var radio = _generator.GenerateRadioButton(ViewContext, For.ModelExplorer, For.Name, enumItem.Key, false, new id);
                var label = _generator.GenerateLabel(ViewContext, For.ModelExplorer, For.Name, name, new @for = id);

                output.PreElement.AppendHtml(radio);
                output.PreElement.AppendHtml(label);
            
        

        /// Computes the variant to be unique for each radiobutton.
        private string VariantId(KeyValuePair<string, string> enumItem) =>
            new StringBuilder()
                .Append(ViewContext.CreateUniqueId(_generator.IdAttributeDotReplacement, For.Name))
                .Append(_generator.IdAttributeDotReplacement)
                .Append(enumItem.Key)
                .ToString();
    

【讨论】:

以上是关于ASP.NET 5 MVC 6 中的单选按钮标记帮助程序的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 jquery unobtrusive 和 Asp.Net Mvc 验证动态生成的单选按钮组?

如何使用jQuery unobtrusive和Asp.Net Mvc验证动态生成的单选按钮组?

如何禁用 ASP.NET MVC 中 HtmlHelper 方法生成的单选按钮和复选框?

如何确定在 C# ASP.NET CORE MVC 5.0 中选择了哪个单选按钮

如何隐藏单选按钮列表中的单选按钮之一?

ASP.NET MVC 单选按钮更新布尔值