【问题标题】:MVC3 Razor DropDownListFor EnumsMVC3 Razor DropDownListFor Enums
【发布时间】:2011-06-07 02:31:14
【问题描述】:

试图让我的项目更新到 MVC3,但我找不到:

我有一个简单的 ENUMS 数据类型:

public enum States()
{
  AL,AK,AZ,...WY
}

我想在包含此数据类型的模型视图中用作 DropDown/SelectList:

public class FormModel()
{
    public States State {get; set;}
}

非常简单:当我为这个部分类使用自动生成视图时,它会忽略这种类型。

我需要一个简单的选择列表,当我通过我的 AJAX - JSON POST 方法点击提交和处理时,将枚举的值设置为所选项目。

比视图(???!):

    <div class="editor-field">
        @Html.DropDownListFor(model => model.State, model => model.States)
    </div>

提前感谢您的建议!

【问题讨论】:

标签: c# asp.net-mvc-3 razor


【解决方案1】:

我在这里找到了一种更简单的解决方案: http://coding-in.net/asp-net-mvc-3-method-extension/

using System;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace EnumHtmlHelper.Helper
{    
    public static class EnumDropDownList
    {
        public static HtmlString EnumDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> modelExpression, string firstElement)
        {
            var typeOfProperty = modelExpression.ReturnType;
            if(!typeOfProperty.IsEnum)
                throw new ArgumentException(string.Format("Type {0} is not an enum", typeOfProperty));     
            var enumValues = new SelectList(Enum.GetValues(typeOfProperty));
            return htmlHelper.DropDownListFor(modelExpression, enumValues, firstElement);
}   }   }

剃刀中的一行就可以了:

@Html.DropDownListFor(model => model.State, new SelectList(Enum.GetValues(typeof(MyNamespace.Enums.States))))

您还可以在链接的文章中找到使用扩展方法执行此操作的代码。

【讨论】:

  • 我认为这个应该被标记为解决方案。最好的不是复杂性而是简单性。
  • 对于那些看起来像 DropDowList 版本的人(比如我):@Html.DropDownList("listName", new SelectList(Enum.GetValues(typeof(MyNamespace.Enums.States))))跨度>
  • @JonEgerton 如果你的意思和我一样,那我同意。如果你想显示枚举 + 描述 + 图像,你会迷失在 Mike McLaughlin 的解决方案中。
  • 我发现这个解决方案的唯一问题是它在加载时没有正确映射选定的值。除此之外,还不错。
  • @triangulito 这根本不是问题 :) @Html.DropDownListFor(model =&gt; model.State, new SelectList(Enum.GetValues(typeof(MyNamespace.Enums.States)),model.State))
【解决方案2】:

我刚刚为我自己的项目制作了一个。下面的代码是我的帮助类的一部分,我希望我得到了所有需要的方法。不行的话写个评论,我再看看。

public static class SelectExtensions
{

    public static string GetInputName<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression)
    {
        if (expression.Body.NodeType == ExpressionType.Call)
        {
            MethodCallExpression methodCallExpression = (MethodCallExpression)expression.Body;
            string name = GetInputName(methodCallExpression);
            return name.Substring(expression.Parameters[0].Name.Length + 1);

        }
        return expression.Body.ToString().Substring(expression.Parameters[0].Name.Length + 1);
    }

    private static string GetInputName(MethodCallExpression expression)
    {
        // p => p.Foo.Bar().Baz.ToString() => p.Foo OR throw...
        MethodCallExpression methodCallExpression = expression.Object as MethodCallExpression;
        if (methodCallExpression != null)
        {
            return GetInputName(methodCallExpression);
        }
        return expression.Object.ToString();
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression) where TModel : class
    {
        string inputName = GetInputName(expression);
        var value = htmlHelper.ViewData.Model == null
            ? default(TProperty)
            : expression.Compile()(htmlHelper.ViewData.Model);

        return htmlHelper.DropDownList(inputName, ToSelectList(typeof(TProperty), value.ToString()));
    }

    public static SelectList ToSelectList(Type enumType, string selectedItem)
    {
        List<SelectListItem> items = new List<SelectListItem>();
        foreach (var item in Enum.GetValues(enumType))
        {
            FieldInfo fi = enumType.GetField(item.ToString());
            var attribute = fi.GetCustomAttributes(typeof(DescriptionAttribute), true).FirstOrDefault();
            var title = attribute == null ? item.ToString() : ((DescriptionAttribute)attribute).Description;
            var listItem = new SelectListItem
                {
                    Value = ((int)item).ToString(),
                    Text = title,
                    Selected = selectedItem == ((int)item).ToString()
                };
            items.Add(listItem);
        }

        return new SelectList(items, "Value", "Text", selectedItem);
    }
}

将其用作:

Html.EnumDropDownListFor(m => m.YourEnum);

更新

我创建了替代的 Html Helpers。使用它们所需要做的就是更改views\web.config 中的基本视图页面。

有了它们,你就可以做到:

@Html2.DropDownFor(m => m.YourEnum);
@Html2.CheckboxesFor(m => m.YourEnum);
@Html2.RadioButtonsFor(m => m.YourEnum);

更多信息在这里:http://blog.gauffin.org/2011/10/first-draft-of-my-alternative-html-helpers/

【讨论】:

  • 好吧,无论哪种方式都可以,我只是收到一个编译错误: 第 41 行:return htmlHelper.DropDownList(inputName, ToSelectList(typeof(TProperty), value.ToString())); 'System.Web.Mvc.HtmlHelper' 不包含 'DropDownList' 的定义,并且无法找到接受类型为 'System.Web.Mvc.HtmlHelper' 的第一个参数的扩展方法 'DropDownList' (您是否缺少 using 指令或程序集引用?)
  • @jordan 我有同样的错误。你设法解决了这个问题吗?
  • @filu @jordan add using System.Web.Mvc.Html; 因为你需要访问SelectExtensionsClass
  • @Para 我遇到了同样的问题,所选值在视图中没有显示为选中状态。 (我必须将 ((int)item).ToString() 更改为 Enum.GetName(enumType, item) 才能将 SelectListItem 正确保存为选中状态,但它仍然不起作用)
  • 刚刚在下面添加了一个涵盖选择问题的答案 - 源于对 DropDownList 重载行为的误解。
【解决方案3】:

ASP.NET MVC 5.1 (RC1) 开始,EnumDropDownListFor 默认包含在HtmlHelper 的扩展方法中。

【讨论】:

    【解决方案4】:

    如果您想要一些非常简单的东西,那么还有另一种方法,具体取决于您在数据库中存储状态的方式。

    如果你有这样的实体:

    public class Address
    {
         //other address fields
    
         //this is what the state gets stored as in the db
         public byte StateCode { get; set; }
    
         //this maps our db field to an enum
         public States State
         {
             get
             {
                 return (States)StateCode;
             }
             set
             {
                 StateCode = (byte)value;
             }
         }
    }
    

    然后生成下拉菜单就这么简单:

    @Html.DropDownListFor(x => x.StateCode,
        from State state in Enum.GetValues(typeof(States))
        select new SelectListItem() { Text = state.ToString(), Value = ((int)state).ToString() }
    );
    

    LINQ 是不是很漂亮?

    【讨论】:

    • 你在哪里定义States enum-在模型或视图中?
    • 在模型中,因为它被模型类使用
    • @stewartml 当我的 ViewModel 具有枚举属性 +“SelectedCodeProperty”时,这是您帖子中的一个属性。为什么不将两者中的枚举作为选定值发送回服务器 + 作为项目值。
    【解决方案5】:

    我能够在一个班轮中做到这一点。

    @Html.DropDownListFor(m=>m.YourModelProperty,new SelectList(Enum.GetValues(typeof(YourEnumType))))
    

    【讨论】:

      【解决方案6】:

      基于@jgauffin 接受的答案,我创建了自己的EnumDropDownListFor 版本,它处理选择项目的问题。

      问题在another SO answer here:中有详细说明,基本上是对DropDownList的不同重载行为的误解。

      我的完整代码(包括htmlAttributes 等的重载是:

      public static class EnumDropDownListForHelper
      {
      
          public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(
                  this HtmlHelper<TModel> htmlHelper, 
                  Expression<Func<TModel, TProperty>> expression
              ) where TModel : class
          {
              return EnumDropDownListFor<TModel, TProperty>(
                                  htmlHelper, expression, null, null);
          }
      
          public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(
                  this HtmlHelper<TModel> htmlHelper, 
                  Expression<Func<TModel, TProperty>> expression, 
                  object htmlAttributes
              ) where TModel : class
          {
              return EnumDropDownListFor<TModel, TProperty>(
                                  htmlHelper, expression, null, htmlAttributes);
          }
      
          public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(
                  this HtmlHelper<TModel> htmlHelper, 
                  Expression<Func<TModel, TProperty>> expression, 
                  IDictionary<string, object> htmlAttributes
              ) where TModel : class
          {
              return EnumDropDownListFor<TModel, TProperty>(
                                  htmlHelper, expression, null, htmlAttributes);
          }
      
          public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(
                  this HtmlHelper<TModel> htmlHelper, 
                  Expression<Func<TModel, TProperty>> expression, 
                  string optionLabel
              ) where TModel : class
          {
              return EnumDropDownListFor<TModel, TProperty>(
                                  htmlHelper, expression, optionLabel, null);
          }
      
          public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(
                  this HtmlHelper<TModel> htmlHelper, 
                  Expression<Func<TModel, TProperty>> expression, 
                  string optionLabel, 
                  IDictionary<string,object> htmlAttributes
              ) where TModel : class
          {
              string inputName = GetInputName(expression);
              return htmlHelper.DropDownList(
                                  inputName, ToSelectList(typeof(TProperty)), 
                                  optionLabel, htmlAttributes);
          }
      
          public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(
                  this HtmlHelper<TModel> htmlHelper, 
                  Expression<Func<TModel, TProperty>> expression, 
                  string optionLabel, 
                  object htmlAttributes
              ) where TModel : class
          {
              string inputName = GetInputName(expression);
              return htmlHelper.DropDownList(
                                  inputName, ToSelectList(typeof(TProperty)), 
                                  optionLabel, htmlAttributes);
          }
      
      
          private static string GetInputName<TModel, TProperty>(
                  Expression<Func<TModel, TProperty>> expression)
          {
              if (expression.Body.NodeType == ExpressionType.Call)
              {
                  MethodCallExpression methodCallExpression 
                                  = (MethodCallExpression)expression.Body;
                  string name = GetInputName(methodCallExpression);
                  return name.Substring(expression.Parameters[0].Name.Length + 1);
      
              }
              return expression.Body.ToString()
                          .Substring(expression.Parameters[0].Name.Length + 1);
          }
      
          private static string GetInputName(MethodCallExpression expression)
          {
              // p => p.Foo.Bar().Baz.ToString() => p.Foo OR throw...
              MethodCallExpression methodCallExpression 
                                  = expression.Object as MethodCallExpression;
              if (methodCallExpression != null)
              {
                  return GetInputName(methodCallExpression);
              }
              return expression.Object.ToString();
          }
      
      
          private static SelectList ToSelectList(Type enumType)
          {
              List<SelectListItem> items = new List<SelectListItem>();
              foreach (var item in Enum.GetValues(enumType))
              {
                  FieldInfo fi = enumType.GetField(item.ToString());
                  var attribute = fi.GetCustomAttributes(
                                             typeof(DescriptionAttribute), true)
                                        .FirstOrDefault();
                  var title = attribute == null ? item.ToString() 
                                    : ((DescriptionAttribute)attribute).Description;
                  var listItem = new SelectListItem
                  {
                      Value = item.ToString(),
                      Text = title,
                  };
                  items.Add(listItem);
              }
      
              return new SelectList(items, "Value", "Text");
          }
      }
      

      我已经写了这个on my blog here

      【讨论】:

      • 这是我遇到的唯一能够正确为我的枚举预先选择相关值的解决方案。谢谢!
      • 太棒了。这绝对应该是公认的答案——它有效;接受的答案没有。
      【解决方案7】:

      这将有助于从枚举中选择一个 int 值: 这里SpecType 是一个int 字段... enmSpecTypeenum

      @Html.DropDownList(
          "SpecType", 
           YourNameSpace.SelectExtensions.ToSelectList(typeof(NREticaret.Core.Enums.enmSpecType), 
           Model.SpecType.ToString()), "Tip Seçiniz", new 
           { 
               gtbfieldid = "33", 
               @class = "small" 
           })
      

      【讨论】:

        【解决方案8】:

        我对 SelectList 方法进行了以下更改,以使其对我来说更好一些。也许它对其他人有用。

        public static SelectList ToSelectList<T>(T selectedItem)
                {
                    if (!typeof(T).IsEnum) throw new InvalidEnumArgumentException("The specified type is not an enum");
        
                    var selectedItemName = Enum.GetName(typeof (T), selectedItem);
                    var items = new List<SelectListItem>();
                    foreach (var item in Enum.GetValues(typeof(T)))
                    {
                        var fi = typeof(T).GetField(item.ToString());
                        var attribute = fi.GetCustomAttributes(typeof(DescriptionAttribute), true).FirstOrDefault();
        
                        var enumName = Enum.GetName(typeof (T), item);
                        var title = attribute == null ? enumName : ((DescriptionAttribute)attribute).Description;
        
                        var listItem = new SelectListItem
                        {
                            Value = enumName,
                            Text = title,
                            Selected = selectedItemName == enumName
                        };
                        items.Add(listItem);
                    }
        
                    return new SelectList(items, "Value", "Text");
                }
        

        【讨论】:

          【解决方案9】:
              public enum EnumStates
              {
                  AL = 0,
                  AK = 1,
                  AZ = 2,
                  WY = 3
              }
          
          
          @Html.DropDownListFor(model => model.State, (from EnumStates e in Enum.GetValues(typeof(EnumStates))
                                                                         select new SelectListItem { Value = ((int)e).ToString(), Text = e.ToString() }), "select", new { @style = "" })
                          @Html.ValidationMessageFor(model => model.State)  //With select
          
          
          
          //Or
          
          
          @Html.DropDownListFor(model => model.State, (from EnumStates e in Enum.GetValues(typeof(EnumStates))
                                                                         select new SelectListItem { Value = ((int)e).ToString(), Text = e.ToString() }), null, new { @style = "" })
                          @Html.ValidationMessageFor(model => model.State)   //With out select
          

          【讨论】:

          • 你在哪里定义 EnumState?
          • 在顶部你可以看到它... public enum EnumStates
          【解决方案10】:

          和迈克的一样(在冗长的回答之间隐藏)

          model.truckimagelocation 是 TruckImageLocation 枚举类型的类实例属性

          @Html.DropDownListFor(model=>model.truckimagelocation,Enum.GetNames(typeof(TruckImageLocation)).ToArray().Select(f=> new SelectListItem() {Text = f, Value = f, Selected = false}))
          

          【讨论】:

            【解决方案11】:

            这是将用于所有枚举的最通用代码。

            public static class UtilitiesClass
            {
            
                public static SelectList GetEnumType(Type enumType)
                {
                    var value = from e in Enum.GetNames(enumType)
                                select new
                                {
                                    ID = Convert.ToInt32(Enum.Parse(enumType, e, true)),
                                    Name = e
                                };
                    return new SelectList(value, "ID", "Name");
                }
            }
            

            动作方法

            ViewBag.Enum= UtilitiesClass.GetEnumType(typeof (YourEnumType));
            

            View.cshtml

             @Html.DropDownList("Type", (IEnumerable<SelectListItem>)ViewBag.Enum, new { @class = "form-control"})
            

            【讨论】:

              【解决方案12】:

              你可以在你的模型中使用枚举

              你的枚举

              public enum States()
              {
                AL,AK,AZ,...WY
              }
              

              制作模型

              public class enumclass
              {
              public States statesprop {get; set;}
              }
              

              在视图中

              @Html.Dropdownlistfor(a=>a.statesprop)
              

              【讨论】:

              • 最新问题解答 kar.
              【解决方案13】:

              MVC5 中最简单的答案是定义枚举:

              public enum ReorderLevels {
                        zero = 0,
                          five = 5,
                          ten = 10,
                          fifteen = 15,
                          twenty = 20,
                          twenty_five = 25,
                          thirty = 30
                      }
              

              在视图中绑定:

                      <div class="form-group">
                          <label>Reorder Level</label>
                          @Html.EnumDropDownListFor(m => m.ReorderLevel, "Choose Me", new { @class = "form-control" })
                      </div>
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多