【问题标题】:MVC4 enum and radio button listMVC4 枚举和单选按钮列表
【发布时间】:2013-08-30 21:59:57
【问题描述】:

我在这方面看到了一些线程,但似乎没有一个适用于 MVC4,因为 RadioButtonFor html 扩展方法/帮助器不存在。

假设我有一个枚举列表 - 即航空公司:

public enum Airlines
{
   Unknown = 0,
   BritishAirways = 1,
   VirginAtlantic = 2,
   AirFrance = 3
}

如何将其绑定到视图上的单选按钮列表并能够检索所选项目? 如果没有选择,那么能够说“选择一项”怎么样?

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-4


    【解决方案1】:

    您可以为枚举 Airlines 创建自定义编辑器模板,该模板将呈现单选按钮列表。在您的模型中,您将拥有Airlines 类型的属性,并使用Required 属性标记此属性并设置ErrorMessage = "select one item"。如果需要,不要忘记在客户端验证中包含 jQuery 验证,通常只需在布局或视图中添加 @Scripts.Render("~/bundles/jqueryval")。如果您不使用 jQuery 验证,则需要使模型上的属性可为空,因为枚举默认设置为第一个值,因此 MVC 不会将其视为无效。请记住,如果您将属性更改为可为空,您还需要将编辑器模板的模型类型也更改为可为空。

    更新

    要使编辑器模板能够为任何枚举呈现单选按钮列表,请将模板更改为以下内容:

    @model Enum
    @foreach (var value in Enum.GetValues(Model.GetType()))
    {
        @Html.RadioButtonFor(m => m, value)
        @Html.Label(value.ToString())
    }
    

    原创

    编辑器模板,Airlines.cshtml,位于 Views\Shared\EditorTemplates 目录中:

    @model MvcTest.Models.Airlines
    @foreach (var value in Enum.GetValues(typeof(MvcTest.Models.Airlines)))
    {
        @Html.RadioButtonFor(m => m, value)
        @Html.Label(value.ToString())
    }
    

    模型:

    public class TestModel
    {
        [Required(ErrorMessage = "select one item")]
        public Airlines Airline { get; set; }
    }
    

    动作方法:

    public class HomeController : Controller
    {
        [HttpGet]
        public ActionResult Index()
        {
            return View(new TestModel());
        }
    
        [HttpPost]
        public ActionResult Index(TestModel model)
        {
            if (ModelState.IsValid)
            {
                return RedirectToAction("Index");
            }
    
            return View(model);
        }
    }
    

    观点:

    @model MvcTest.Models.TestModel
    @{
        ViewBag.Title = "Index";
        Layout = "~/Views/Shared/_Layout.cshtml";
    }
    <h2>Index</h2>
    @using (Html.BeginForm())
    {
        @Html.EditorFor(m => m.Airline)
        <input type="submit" value="Submit" />
        @Html.ValidationSummary(false)
    }
    

    【讨论】:

    • 谢谢!我会试试这个,很快就会回复你。如果我不希望某个枚举显示在列表中,我该怎么办?可以说我正在处理的所有枚举都将具有“未知”。我怎样才能确保它不会被渲染,但又能确保在列表中选择了一个值?
    • OK 尝试这个对我来说不太奏效。我没有得到单选按钮列表,而只是一个文本框。我怎样才能制作一个局部视图并给它枚举并让该局部视图获取枚举并通常为枚举中的每个项目吐出单选按钮,但还要让回发/提交将所选值绑定到视图模型?
    • 如果您想将某个值保留在列表之外,只需在循环中放置 if 语句并检查它。创建局部视图而不是编辑器模板应该相当容易,区别只是语义,因为编辑器模板是局部视图。只需在您想要的任何 view\controller 目录中创建一个局部视图,尽管将其放在共享目录中可能更有意义,然后将代码从编辑器模板复制到其中。比使用@Html.Partial("partialViewName", model) 并将主视图模型中的枚举作为模型传递。
    • 我不知道你为什么得到一个文本框而不是单选按钮列表。当我在本地运行它时,我发布的代码对我有用。尝试检查您的代码并确保它与我发布的内容完全一致。
    • 我也得到了文本框,editorfor怎么知道它应该使用那个editortemplate(一个带有@model Enum的)?
    【解决方案2】:

    我建议对其他答案采用类似的方法,但使用以下编辑器模板; EnumRadioButtonList.cshtml,在 Views\Shared\EditorTemplates 目录中:

    @model Enum
    @foreach (var value in Enum.GetValues(Model.GetType()))
    {
        var id = TagBuilder.CreateSanitizedId(string.Format(
            "{0}_{1}_{2}", ViewData.TemplateInfo.HtmlFieldPrefix, Model.GetType(), value));
        <div>
            @Html.RadioButton(string.Empty, value, value.Equals(Model), new { id })
            @Html.Label(value.ToString(), new { @for = id })
        </div>
    }
    

    每个单选按钮的 HTML id 必须是唯一的。因此,上面的代码通过使用ViewData.TemplateInfo.HtmlFieldPrefixid 前面加上绑定属性的名称。如果模型包含使用此枚举的多个属性,并且每个属性都使用此编辑器模板,这将确保唯一的 ids。

    每个单选按钮随附的label 将正确设置其for 属性。 这意味着用户可以通过单击标签文本来选择单选按钮,这是一个比单选按钮本身更大更好的点击目标。

    对于 MVC 模型绑定,单选按钮都将其 HTML name 属性值设置为在 EditorFor 调用中指定的属性值(在这种情况下为 Airline)。

    使用它:

    @Html.EditorFor(m => m.Airline, "EnumRadioButtonList")
    

    【讨论】:

    • 这个解决方案非常适合编辑页面。但是,在尚未为枚举单选按钮选择项目的创建页面中,我得到“对象引用未设置为对象的实例”。有解决这个问题的办法吗?
    • 感谢@RichardEverett。我实例化了模型对象,然后将它传递给视图,它现在可以工作了。
    【解决方案3】:

    RadioButtonFor 不存在是什么意思?我使用 MVC4 并在我的代码中使用它。对于一个列表,您可以将多个设置为相同的名称

    @Html.RadioButtonFor(x => x.Airlines, Airlines.Unknown)
    @Html.RadioButtonFor(x => x.Airlines, Airlines.BritishAirways)
    @Html.RadioButtonFor(x => x.Airlines, Airlines.VirginAtlantic)
    @Html.RadioButtonFor(x => x.Airlines, Airlines.AirFrance)
    

    这些将与模型相关联,因此在回发时您会看到航空公司设置为所选项目,并且在加载页面时将选择匹配的单选按钮。

    【讨论】:

    • 我认为 Ahmed 的意思是 RadioButtonFor 在 MVC4 之前 不存在,并且他发现的示例没有使用辅助方法。
    • 我不确定我是否遵循。一般来说,像这样的列表我只有一个标签在顶部说选择最好的......
    • RadioButtonFor 使用type="radio" 呈现HTML input 元素。通常,您还会在每个 HTML label 旁边添加一个 for 属性,其值与随附单选按钮的 id 匹配。
    • 在这个例子中应该可以只做@Html.LabelFor(x => x.Airlines)。
    • 我已经用我建议的方法添加了答案。
    【解决方案4】:

    我能够将其他答案中的一些方法与一些附加功能相结合:

    EnumRadioButtonList.cshtml

    @model Enum
    @foreach (var item in EnumHelper.GetSelectList(Model.GetType()))
    {
        <div class="radio">
            <label>
                @Html.RadioButton(string.Empty, item.Value, Model.Equals(Enum.Parse(Model.GetType(), item.Value)))
                @item.Text
            </label>
        </div>
    }
    

    这使用EnumHelper.GetSelectList() 作为一种hack,以便您可以对枚举成员使用显示属性:

    public enum TestEnum
    {
        First,
        [Display(Name = "Second Member")]
        Second,
        Third
    }
    

    用法:

    @Html.EditorFor(m => m.TestEnumProperty, "EnumRadioButtonList")
    

    产量:

    Image

    我还使用 Bootstrap 单选按钮样式和单独的内联版本帮助器:

    EnumRadioButtonListInline.cshtml

    @model Enum
    @foreach (var item in EnumHelper.GetSelectList(Model.GetType()))
    {
        <label class="radio-inline">
            @Html.RadioButton(string.Empty, item.Value, Model.Equals(Enum.Parse(Model.GetType(), item.Value)))
            @item.Text
        </label>
    }
    

    【讨论】:

      【解决方案5】:

      我将评分最高的答案提高了asymptoticfault 一点,以反映所选值。 将此作为 EnumRadioButton.cshtml 保存到您的共享视图 EditorTemplates 文件夹中:

      @model Enum
      @foreach (var value in Enum.GetValues(Model.GetType()))
      {
          if (Equals(Model, value))
          {
              @Html.RadioButtonFor(m => m, value, new {@checked = "checked"})
          }
          else
          {
              @Html.RadioButtonFor(m => m, value)
          }
      
          @Html.Label(value.ToString())
      }
      

      用法:

      @Html.EditorFor(item => Model.MyEnumType, "EnumRadioButton")
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-03-01
        • 2015-08-07
        • 1970-01-01
        • 1970-01-01
        • 2011-01-29
        • 2013-07-16
        • 2020-09-01
        • 1970-01-01
        相关资源
        最近更新 更多