【问题标题】:MVC 2 - Passing enum to CheckBoxForMVC 2 - 将枚举传递给 CheckBoxFor
【发布时间】:2011-05-10 19:25:06
【问题描述】:

假设我们有一个模型:

public class Document
{
    public string Name { get; set;}
    public List<DayOfWeek> WeekDays { get; set; }
}

是否可以为该模型呈现代表星期几的复选框? 我已经搜索了互联网,但没有找到任何解决方案。

我的意思是它适用于CheckBoxFor(model=&gt; model.SomeProperty),但如果SomePropertyList&lt;DayOfWeek&gt;,它就不起作用。 DayOfWeek 这是一个枚举。

提前致谢。

【问题讨论】:

    标签: c# asp.net asp.net-mvc asp.net-mvc-2 enums


    【解决方案1】:

    这将需要更改您的 DayOfWeek 枚举,但我更喜欢将其作为一个标志(不那么混乱,只有一个值等)。有趣的是,微软还在他们的enum flags documentation 中使用了一周中的几天。

    DayOfWeek 枚举使用位标志:

    [Flags]//<-- Note the Flags attribute
    public enum DayOfWeek
    {
      Monday = 1,
      Tuesday = 2,
      Wednesday = 4,
      Thursday = 8,
      Friday = 16,
      Saturday = 32,
      Sunday = 64,
    }
    

    型号:

    public class Document
    {
      public string Name { get; set;}
    
      //Note that WeekDays is no longer a collection.
      public DayOfWeek WeekDays { get; set; }
    }
    

    查看:

    <% foreach(DayOfWeek dayOfWeek in Enum.GetValues(typeof(DayOfWeek))) { %>
      <label>
        <!-- The HasFlag stuff is optional and is just there to show how it would be populated if you're doing a `GET` request. -->
        <input type="checkbox" name="WeekDays[]" value="<%= (int)dayOfWeek%>" <%= Model.WeekDays.HasFlag(dayOfWeek) ? "checked='checked'" : "" %>" />
        <%= dayOfWeek %>
      </label>
    <% } %>
    

    控制器:

    [HttpPost]
    public ActionResult MyPostedPage(MyModel model)
    {
      //I moved the logic for setting this into a helper because this could be re-used elsewhere.
      model.WeekDays = Enum<DayOfWeek>.ParseToEnumFlag(Request.Form, "WeekDays[]");
      ...
    }
    

    ParseToEnumFlag 的快速助手:

    public static class Enum<T>
    {
      public static T ParseToEnumFlag(NameValueCollection source, string formKey)
      {
        //MVC 'helpfully' parses the checkbox into a comma-delimited list. We pull that out and sum the values after parsing it back into the enum.
        return (T)Enum.ToObject(typeof(T), source.Get(formKey).ToIEnumerable<int>(',').Sum());
      }
    }
    

    背景: 枚举标志值采用几何系列 (1,2,4,8...) 的原因是,当这些值相加时,只有一种可能的组合。例如,我们会知道31 只能是周一、周二、周三、周四和周五 (1 + 2 + 4 + 8 + 16)。

    更新 - 2012 年 9 月 3 日

    看来我错过了 ToIEnumerable(),它是我们源代码中的一个扩展。它采用分隔字符串并将其转换为 IEnumerable,因此非常适合逗号分隔的数字。感谢@escist 的提醒。

    public static IEnumerable<T> ToIEnumerable<T>(this string source, char delimiter)
    {
      return source.Split(new char[] { delimiter }, StringSplitOptions.RemoveEmptyEntries).Select(x => (T)Convert.ChangeType(x, typeof(T)));
    }
    

    【讨论】:

    • 我无法编译这个。 sn -p source.Get(formKey).ToIEnumerable&lt;int&gt;(',').Sum()) 给出编译错误
    • @DanAtkinson 我喜欢这个答案,但我在将视图转换为 Razor 视图时遇到了一些麻烦(我正在使用 ASP.NET MVC 4)。您能否编写此版本的 Razor View 版本或提供有关如何转换它的链接?谢谢。
    【解决方案2】:

    您可以枚举枚举的值并手动创建复选框。对每个复选框使用相同的name 会将它们作为数组提交到 ActionMethod 中。

    <% foreach(var value in Enum.GetValues(typeof(DayOfWeek))) { %>
         <% var name = Enum.GetName(typeof(DayOfWeek), value); %>
         <label for="dayofweek<%=value %>"><%=name %></label>
         <input type="checkbox" id="dayofweek<%=value %>" name="dayofweek" value="<%=value %>" />
    <% } %>
    

    您的操作方法类似于:

    public ActionResult Save(DayOfWeek[] dayofweek)
    {
         // Do Stuff
    }
    

    【讨论】:

      【解决方案3】:

      根据 Dan Atkinson 的(很棒的)回答,我在这里和那里做了一些捷径。我的建议是:

      与 [Flags] 和模型相同的枚举

      对于View,我不会将类型更改为int,而是将复选框值保留为string

      <input type="checkbox" name="WeekDays[]" 
             value="<%= dayOfWeek %>" 
             <%= Model.WeekDays.HasFlag(dayOfWeek) ? "checked='checked'" : "" %>" />
      

      这使得 Controller 更加简单:

      [HttpPost]
      public ActionResult MyPostedPage(MyModel model)
      {
          string days = Request.Form.get("WeekDays[]");
          if (days == null) {
              model.WeekDays = 0;  // Depending whether you allow neither day to be selected
                                   // you can handle this differently
          } else {
              model.WeekDays = (WeekDays)Enum.Parse(typeof(WeekDays), days);
          }
      
          ...
       }
      

      注意,代码根本不使用扩展。

      干杯,

      【讨论】:

        【解决方案4】:

        您可以创建自己的自定义模板,该模板知道如何获取枚举列表并将其转换为复选框。然后,您必须调整模型绑定器以根据检查值处理绑定枚举。由于您的问题缺乏细节,我不确定该模型的用例是什么。

        这是您在视图中内联它的方式:

        <% foreach(var dayOfWeek in Model.WeekDays) { %>
            <%= dayOfWeek.ToString() %><%= Html.CheckBox(dayOfWeek.ToString()) %>
        <% } %>
        

        【讨论】:

        • 感谢您的回答。我只想使用包含星期几的 DayOfWeek 枚举器。每个 Document 对象都包含一个日期列表。我想为这个类创建复选框,这样就可以选择多天。例如 CheckBoxFor(model=> model.SomeProperty) 工作完美,但如果 SomeProperty 是 List
        【解决方案5】:

        注意:当使用声明为 var 的 dayOfWeek 时,我在视图中使用 HasFlag() 实现 Dan 的答案时遇到问题。我必须将其声明为 DayOfWeek 枚举。

        查看:

        <% foreach(DayOfWeek dayOfWeek in Enum.GetValues(typeof(DayOfWeek))) { %>
          <label>
            <!-- The HasFlag stuff is optional and is just there to show how it would be populated if you're doing a `GET` request. -->
            <input type="checkbox" name="WeekDays[]" value="<%= (int)dayOfWeek%>" <%= Model.WeekDays.HasFlag(dayOfWeek) ? "checked='checked'" : "" %>" />
            <%= dayOfWeek %>
          </label>
        <% } %>
        

        我也遇到了 helper 中的 ToIEnumerable 函数,因为没有具有该名称的函数(至少对我而言)。

        【讨论】:

        • 我已将 DayOfWeek(而不是 var)和 ToIEnumerable() 添加到我的答案中。
        猜你喜欢
        • 1970-01-01
        • 2011-08-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-07
        • 2012-01-14
        • 1970-01-01
        相关资源
        最近更新 更多