MVC 2 – 将枚举传递给CheckBoxFor

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

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

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

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

提前致谢。

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

 <% foreach(var value in Enum.GetValues(typeof(DayOfWeek))) { %> <% var name = Enum.GetName(typeof(DayOfWeek), value); %>   <% } %> 

你的行动方法是这样的:

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

这需要更改你的DayOfWeek枚举,但我赞成将它作为一个标志(不那么杂乱,只有一个值等)。 有趣的是,微软还在其enum flags文档中使用了一周中的几天。

使用位标志的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))) { %>  <% } %> 

控制器:

 [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.ParseToEnumFlag(Request.Form, "WeekDays[]"); ... } 

ParseToEnumFlag的快速帮助:

 public static class Enum { 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(',').Sum()); } } 

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

更新 - 2012年9月3日

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

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

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

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

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

注意:当使用声明为var的dayOfWeek时,我在视图中使用HasFlag()实现Dan的答案时遇到了问题。 我不得不宣布它为DayOfWeek Enum。

视图:

 <% foreach(DayOfWeek dayOfWeek in Enum.GetValues(typeof(DayOfWeek))) { %>  <% } %> 

我也曾在helper中使用ToIEnumerable函数,因为没有该名称的函数(至少对我而言)。

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

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

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

 " /> 

这使得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); } ... } 

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

干杯,