2012-03-24 132 views
0

比方说,你有一个这样的枚举:这样自定义验证服务器和客户端

public enum ColorsEnum 
{ 
    Undefined, 
    Blue, 
    Red, 
    Green 
} 

和模型:

public class Foo 
{ 
    public ColorsEnum PreferedColor { get; set; } 
} 

有了这样的观点:

@model WebUI.Models.Foo 

@using (Html.BeginForm()) 
{ 
    @Html.LabelFor(m => m.PreferedColor) 
    @Html.DropDownListForEnum(m => m.PreferedColor) 
    <input type="submit"> 
} 

下面是DropdownListForEnum助手:

public static IHtmlString DropDownListForEnum<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, 
                    Expression<Func<TModel, TProperty>> expression) 
    { 
     var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); 
     if (metaData.ModelType.IsEnum) 
     { 
      var names = Enum.GetNames(metaData.ModelType); 
      var translatedNames = GetTranslatedNames(metaData.ModelType); 

      var query = from p in names 
         select new SelectListItem 
            { 
             Text = translatedNames.ContainsKey(p) ? translatedNames[p] : p, 
             Value = p, 
             Selected = false 
            }; 

      return htmlHelper.DropDownList(metaData.PropertyName, query.ToList()); 
     } 
     else 
     { 
      throw new ApplicationException(
       "The DropDownListForEnum helper function must be used with an enum property"); 
     } 
    } 

我的问题:您如何执行验证(客户端&服务器端)以确保用户选择了有效的颜色?验证过程应拒绝“未定义”的颜色。

感谢。

回答

0

我会用一个可空枚举和视图模型的必需属性:

public class MyViewModel 
{ 
    [Required] 
    public ColorsEnum? PreferedColor { get; set; } 
} 

所以,你可以从你的枚举定义中移除Undefined值:

public enum ColorsEnum 
{ 
    Blue, 
    Red, 
    Green 
} 

,然后稍微修改帮手:

public static class HtmlExtensions 
{ 
    public static IHtmlString DropDownListForEnum<TModel, TProperty>(
     this HtmlHelper<TModel> htmlHelper, 
     Expression<Func<TModel, TProperty>> expression 
    ) 
    { 
     var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); 
     var enumType = Nullable.GetUnderlyingType(metaData.ModelType); 
     if (enumType == null || !enumType.IsEnum) 
     { 
      throw new ApplicationException(
       "The DropDownListForEnum helper function must be used with a nullable enum property" 
      ); 
     } 

     var names = Enum.GetNames(enumType); 
     var translatedNames = GetTranslatedNames(metaData.ModelType); 

     var query = 
      from p in names 
      select new SelectListItem 
      { 
       Text = translatedNames.ContainsKey(p) ? translatedNames[p] : p, 
       Value = p, 
       Selected = false 
      }; 
     return htmlHelper.DropDownList(
      metaData.PropertyName, 
      query.ToList(), 
      "-- Select a color --" 
     ); 
    } 
} 

然后有一个简单的控制LER测试:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     return View(new MyViewModel()); 
    } 

    [HttpPost] 
    public ActionResult Index(MyViewModel model) 
    { 
     return View(model); 
    } 
} 

和相应的视图:

@model MyViewModel 

<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script> 

@using (Html.BeginForm()) 
{ 
    @Html.LabelFor(m => m.PreferedColor) 
    @Html.DropDownListForEnum(m => m.PreferedColor) 
    <input type="submit" /> 
} 
+0

Thant对我来说更加清晰。谢谢。 – Bronzato 2012-03-25 08:54:14

0

如果您打算与DropDownListForEnum利用一切枚举的第一个值始终是应该由验证被拒绝“默认”选项,你可能会考虑利用DropDownListoptionLabel参数。

弹出query中的第一个元素,并将该字符串作为DropDownList中的第三个参数传递。

return htmlHelper.DropDownList(metaData.PropertyName, query.ToList(), 
    /* some string containing default value extracted from your enum */); 

这样一来,使用DropDownListForEnum将使用枚举的第一个值作为“默认”值创建的所有的DDL,和所有你必须做的验证是一个[Required]数据注释添加到PreferredColor

或者,您可以删除您枚举的Default选项,让你的HtmlHelper(或创建一个新的)采取了第三个参数,包含optionLabel一个字符串,将传递给DropDownList

无论哪种方式,这个想法是利用optionLabel作为验证器将为您做所有的工作。

+0

非常感谢你。它使得更多的使用optionLabel。所以我删除了我的枚举(未定义)的第一个值,并使用了一个选项标签。但是当生成视图时,选项标签(“请选择...”)未被选中,这始终是我枚举中的第一项?任何想法? – Bronzato 2012-03-24 16:23:19

+0

我认为这可能是因为DDL绑定到PreferredColor,并且在移除Default之后,PreferredColor的默认值变为蓝色。我更熟悉绑定到整数的DDL,所以我忽略了这一点。另一种方法是将Default保留在枚举中,但在DropDownListForEnum中使用bool参数,该参数告诉HtmlHelper是否将第一个值提取为optionLabel。这样,无论默认选项是否包含在枚举中,都可以在所有枚举上使用它。 – nightshifted 2012-03-24 16:34:24

+0

@nightshifted另一种可能是将字符串[] excludeList添加到参数中,以便您可以选择查看排除枚举中的任何元素。会提供相同的最终结果,但更灵活一点? – dreza 2012-03-24 20:29:22