MVC 2 - 将枚举传递给CheckBoxFor

时间:2010-11-16 12:55:42

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

我们假设我们有一个模型:

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

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

我的意思是它适用CheckBoxFor(model=> model.SomeProperty),但如果SomePropertyList<DayOfWeek>则不起作用。 DayOfWeek这里是一个枚举。

提前致谢。

5 个答案:

答案 0 :(得分:18)

这需要更改你的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)));
}

答案 1 :(得分:12)

您可以枚举枚举值并手动创建复选框。对每个复选框使用相同的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
}

答案 2 :(得分:1)

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

这就是你在视图中内嵌的方式:

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

答案 3 :(得分:1)

注意:在使用声明为var的HasFlag()时,我在视图中使用dayOfWeek实现了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函数,因为没有该名称的函数(至少对我而言)。

答案 4 :(得分:1)

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

与[标志]和模型相同的枚举。

对于查看,我不会将类型更改为int,但会将复选框值保留为string

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

这使控制器更加简单:

[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);
    }

    ...
 }

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

干杯,