it-swarm.asia

كيف يمكنك إنشاء قائمة منسدلة من التعداد في ASP.NET MVC؟

أحاول استخدام طريقة الامتداد Html.DropDownList لكن لا يمكنني معرفة كيفية استخدامها مع التعداد.

دعنا نقول لدي تعداد مثل هذا:

public enum ItemTypes
{
    Movie = 1,
    Game = 2,
    Book = 3
}

كيف يمكنني إنشاء قائمة منسدلة باستخدام هذه القيم باستخدام طريقة امتداد Html.DropDownList؟

أو هل أفضل رهان هو إنشاء حلقة من أجل إنشاء عناصر Html يدويًا؟

627
Kevin Pang

ل MVC v5.1 استخدام Html.EnumDropDownListFor

@Html.EnumDropDownListFor(
    x => x.YourEnumField,
    "Select My Type", 
    new { @class = "form-control" })

ل MVC v5 استخدم EnumHelper

@Html.DropDownList("MyType", 
   EnumHelper.GetSelectList(typeof(MyType)) , 
   "Select My Type", 
   new { @class = "form-control" })

ل MVC 5 و أقل

توالت إجابة رون في طريقة التمديد:

namespace MyApp.Common
{
    public static class MyExtensions{
        public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
            where TEnum : struct, IComparable, IFormattable, IConvertible
        {
            var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                select new { Id = e, Name = e.ToString() };
            return new SelectList(values, "Id", "Name", enumObj);
        }
    }
}

هذا يسمح لك بالكتابة:

ViewData["taskStatus"] = task.Status.ToSelectList();

بواسطة using MyApp.Common

792
Martin Faartoft

أعلم أنني متأخرة عن هذا الأمر ، لكنني اعتقدت أنك قد تجد هذا المتغير مفيدًا ، حيث يتيح لك هذا أيضًا استخدام الجمل الوصفية بدلاً من ثوابت التعداد في القائمة المنسدلة. للقيام بذلك ، قم بتزيين كل إدخال تعداد بسمة [System.ComponentModel.Description].

فمثلا:

public enum TestEnum
{
  [Description("Full test")]
  FullTest,

  [Description("Incomplete or partial test")]
  PartialTest,

  [Description("No test performed")]
  None
}

هنا هو الكود الخاص بي:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Reflection;
using System.ComponentModel;
using System.Linq.Expressions;

 ...

 private static Type GetNonNullableModelType(ModelMetadata modelMetadata)
    {
        Type realModelType = modelMetadata.ModelType;

        Type underlyingType = Nullable.GetUnderlyingType(realModelType);
        if (underlyingType != null)
        {
            realModelType = underlyingType;
        }
        return realModelType;
    }

    private static readonly SelectListItem[] SingleEmptyItem = new[] { new SelectListItem { Text = "", Value = "" } };

    public static string GetEnumDescription<TEnum>(TEnum value)
    {
        FieldInfo fi = value.GetType().GetField(value.ToString());

        DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

        if ((attributes != null) && (attributes.Length > 0))
            return attributes[0].Description;
        else
            return value.ToString();
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
    {
        return EnumDropDownListFor(htmlHelper, expression, null);
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes)
    {
        ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        Type enumType = GetNonNullableModelType(metadata);
        IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();

        IEnumerable<SelectListItem> items = from value in values
            select new SelectListItem
            {
                Text = GetEnumDescription(value),
                Value = value.ToString(),
                Selected = value.Equals(metadata.Model)
            };

        // If the enum is nullable, add an 'empty' item to the collection
        if (metadata.IsNullableValueType)
            items = SingleEmptyItem.Concat(items);

        return htmlHelper.DropDownListFor(expression, items, htmlAttributes);
    }

يمكنك بعد ذلك القيام بذلك في طريقة العرض الخاصة بك:

@Html.EnumDropDownListFor(model => model.MyEnumProperty)

آمل أن يساعدك هذا!

** EDIT 2014-JAN-23: أصدرت Microsoft للتو MVC 5.1 ، والذي أصبح لديه الآن ميزة EnumDropDownListFor. للأسف ، لا يبدو أنها تحترم السمة [الوصف] ، لذا فإن الكود أعلاه لا يزال قائماً. انظر قسم التعداد في ملاحظات إصدار Microsoft لـ MVC 5.1.

التحديث: يدعم عرض السمة [Display(Name = "Sample")] ، لذلك يمكن للمرء استخدام ذلك.

[تحديث - لاحظت هذا للتو ، والرمز يشبه نسخة موسعة من التعليمات البرمجية هنا: https://blogs.msdn.Microsoft.com/stuartleeks/2010/05/21/asp-net-mvc-creating- a-dropdownlist-helper-for-enums/ ، مع اثنين من الإضافات. إذا كان الأمر كذلك ، فإن الإسناد يبدو عادلاً ؛-)]

349
SimonGoldstone

فيASP.NET MVC 5.1، أضافوا المساعد EnumDropDownListFor() ، لذلك لا حاجة إلى ملحقات مخصصة:

نموذج:

public enum MyEnum
{
    [Display(Name = "First Value - desc..")]
    FirstValue,
    [Display(Name = "Second Value - desc...")]
    SecondValue
}

رأي:

@Html.EnumDropDownListFor(model => model.MyEnum)

(استخدام الوسم المساعد (ASP.NET MVC 6):

<select asp-for="@Model.SelectedValue" asp-items="Html.GetEnumSelectList<MyEnum>()">
185
Ofiris

لقد تصطدم بنفس المشكلة ، وجدت هذا السؤال ، واعتقدت أن الحل الذي قدمه الرماد لم يكن ما كنت أبحث عنه ؛ الحاجة إلى إنشاء HTML بنفسي تعني مرونة أقل مقارنة بوظيفة Html.DropDownList() المضمنة.

يتحول C # 3 وما إلى ذلك يجعل من السهل جدا. لدي enum يسمى TaskStatus:

var statuses = from TaskStatus s in Enum.GetValues(typeof(TaskStatus))
               select new { ID = s, Name = s.ToString() };
ViewData["taskStatus"] = new SelectList(statuses, "ID", "Name", task.Status);

يؤدي هذا إلى إنشاء ol SelectList جيد يمكن استخدامه كما اعتدت عليه في طريقة العرض:

<td><b>Status:</b></td><td><%=Html.DropDownList("taskStatus")%></td></tr>

نوع مجهول و LINQ يجعل هذا IMHO أكثر أناقة. لا جريمة المقصود ، الرماد. :)

126
Rune Jacobsen

هنا حل مغلف بشكل أفضل:

https://www.spicelogic.com/Blog/enum-dropdownlistfor-asp-net-mvc-5

قل هنا هو النموذج الخاص بك:

enter image description here

استخدام العينة:

enter image description here

واجهة المستخدم التي تم إنشاؤها:  enter image description here

وإنشاء HTML

enter image description here

لقطة المفاجئة لتعليمات مصدر التعليمات المساعد:

enter image description here

يمكنك تنزيل نموذج المشروع من الرابط الذي قدمته.

تحرير: إليك الكود:

public static class EnumEditorHtmlHelper
{
    /// <summary>
    /// Creates the DropDown List (HTML Select Element) from LINQ 
    /// Expression where the expression returns an Enum type.
    /// </summary>
    /// <typeparam name="TModel">The type of the model.</typeparam>
    /// <typeparam name="TProperty">The type of the property.</typeparam>
    /// <param name="htmlHelper">The HTML helper.</param>
    /// <param name="expression">The expression.</param>
    /// <returns></returns>
    public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression) 
        where TModel : class
    {
        TProperty value = htmlHelper.ViewData.Model == null 
            ? default(TProperty) 
            : expression.Compile()(htmlHelper.ViewData.Model);
        string selected = value == null ? String.Empty : value.ToString();
        return htmlHelper.DropDownListFor(expression, createSelectList(expression.ReturnType, selected));
    }

    /// <summary>
    /// Creates the select list.
    /// </summary>
    /// <param name="enumType">Type of the enum.</param>
    /// <param name="selectedItem">The selected item.</param>
    /// <returns></returns>
    private static IEnumerable<SelectListItem> createSelectList(Type enumType, string selectedItem)
    {
        return (from object item in Enum.GetValues(enumType)
                let fi = enumType.GetField(item.ToString())
                let attribute = fi.GetCustomAttributes(typeof (DescriptionAttribute), true).FirstOrDefault()
                let title = attribute == null ? item.ToString() : ((DescriptionAttribute) attribute).Description
                select new SelectListItem
                  {
                      Value = item.ToString(), 
                      Text = title, 
                      Selected = selectedItem == item.ToString()
                  }).ToList();
    }
}
59
Emran Hussain

يتطلب Html.DropDownListFor فقط IEnumerable ، لذلك يعد بديل حل Prise كما يلي. هذا سوف يسمح لك ببساطة الكتابة:

@Html.DropDownListFor(m => m.SelectedItemType, Model.SelectedItemType.ToSelectList())

[حيث يكون SelectedItemType عبارة عن حقل في طرازك من أنواع العناصر ، ونموذجك غير فارغ]

أيضًا ، لا تحتاج حقًا إلى إنشاء طريقة الامتداد حيث يمكنك استخدام enumValue.GetType () بدلاً من typeof (T).

تحرير: حل سيمون المتكاملة هنا أيضا ، وشملت طريقة تمديد ToDescription.

public static class EnumExtensions
{
    public static IEnumerable<SelectListItem> ToSelectList(this Enum enumValue)
    {
        return from Enum e in Enum.GetValues(enumValue.GetType())
               select new SelectListItem
               {
                   Selected = e.Equals(enumValue),
                   Text = e.ToDescription(),
                   Value = e.ToString()
               };
    }

    public static string ToDescription(this Enum value)
    {
        var attributes = (DescriptionAttribute[])value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
        return attributes.Length > 0 ? attributes[0].Description : value.ToString();
    }
}
47
Zaid Masud

لذلك بدون وظائف الإرشاد إذا كنت تبحث عن بسيط وسهل .. هذا ما فعلته

<%= Html.DropDownListFor(x => x.CurrentAddress.State, new SelectList(Enum.GetValues(typeof(XXXXX.Sites.YYYY.Models.State))))%>

حيث XXXXX.Sites.YYYY.Models.State هو تعداد

من الأفضل القيام بوظيفة المساعد ، ولكن عندما يكون الوقت قصيرًا ، ستنجز المهمة.

32
Marty Trenouth

توسيع إجابات Prize و Rune ، إذا كنت ترغب في الحصول على سمة قيمة لتعيين عناصر القائمة المحددة الخاصة بك إلى قيمة عدد صحيح لنوع التعداد ، بدلاً من قيمة السلسلة ، استخدم الكود التالي:

public static SelectList ToSelectList<T, TU>(T enumObj) 
    where T : struct
    where TU : struct
{
    if(!typeof(T).IsEnum) throw new ArgumentException("Enum is required.", "enumObj");

    var values = from T e in Enum.GetValues(typeof(T))
                 select new { 
                    Value = (TU)Convert.ChangeType(e, typeof(TU)),
                    Text = e.ToString() 
                 };

    return new SelectList(values, "Value", "Text", enumObj);
}

بدلاً من التعامل مع كل قيمة Enumeration ككائن TEnum ، يمكننا التعامل معها ككائن ثم تحويلها إلى عدد صحيح للحصول على القيمة غير المعبأة.

ملاحظة: لقد أضفت أيضًا قيدًا عامًا للنوع لتقييد الأنواع التي يكون هذا الملحق متاحًا لها فقط للهيئات (النوع الأساسي لـ Enum) ، والتحقق من صحة نوع وقت التشغيل والذي يضمن أن البنية التي تم تمريرها هي بالفعل تعداد .

التحديث 10/23/12: تمت إضافة معلمة نوع عام للنوع الأساسي ومسألة عدم التجميع الثابتة التي تؤثر على .NET 4+.

22
Nathan Taylor

أفضل حل وجدت لهذا هو الجمع بين هذه المدونة مع إجابة Simon Goldstone .

هذا يسمح باستخدام التعداد في النموذج. تتمثل الفكرة الأساسية في استخدام خاصية عدد صحيح وكذلك التعداد ومحاكاة خاصية عدد صحيح.

ثم استخدم سمة [System.ComponentModel.Description] للتعليق على النموذج باستخدام نص العرض الخاص بك ، واستخدم ملحق "EnumDropDownListFor" في طريقة العرض الخاصة بك.

هذا يجعل كل من العرض والنموذج قابلاً للقراءة وصيانتهما.

نموذج:

public enum YesPartialNoEnum
{
    [Description("Yes")]
    Yes,
    [Description("Still undecided")]
    Partial,
    [Description("No")]
    No
}

//........

[Display(Name = "The label for my dropdown list")]
public virtual Nullable<YesPartialNoEnum> CuriousQuestion{ get; set; }
public virtual Nullable<int> CuriousQuestionId
{
    get { return (Nullable<int>)CuriousQuestion; }
    set { CuriousQuestion = (Nullable<YesPartialNoEnum>)value; }
}

رأي:

@using MyProject.Extensions
{
//...
    @Html.EnumDropDownListFor(model => model.CuriousQuestion)
//...
}

التمديد (مباشرة من إجابة سيمون جولدستون ، المدرجة هنا من أجل اكتمالها):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel;
using System.Reflection;
using System.Linq.Expressions;
using System.Web.Mvc.Html;

namespace MyProject.Extensions
{
    //Extension methods must be defined in a static class
    public static class MvcExtensions
    {
        private static Type GetNonNullableModelType(ModelMetadata modelMetadata)
        {
            Type realModelType = modelMetadata.ModelType;

            Type underlyingType = Nullable.GetUnderlyingType(realModelType);
            if (underlyingType != null)
            {
                realModelType = underlyingType;
            }
            return realModelType;
        }

        private static readonly SelectListItem[] SingleEmptyItem = new[] { new SelectListItem { Text = "", Value = "" } };

        public static string GetEnumDescription<TEnum>(TEnum value)
        {
            FieldInfo fi = value.GetType().GetField(value.ToString());

            DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

            if ((attributes != null) && (attributes.Length > 0))
                return attributes[0].Description;
            else
                return value.ToString();
        }

        public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
        {
            return EnumDropDownListFor(htmlHelper, expression, null);
        }

        public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            Type enumType = GetNonNullableModelType(metadata);
            IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();

            IEnumerable<SelectListItem> items = from value in values
                                                select new SelectListItem
                                                {
                                                    Text = GetEnumDescription(value),
                                                    Value = value.ToString(),
                                                    Selected = value.Equals(metadata.Model)
                                                };

            // If the enum is nullable, add an 'empty' item to the collection
            if (metadata.IsNullableValueType)
                items = SingleEmptyItem.Concat(items);

            return htmlHelper.DropDownListFor(expression, items, htmlAttributes);
        }
    }
}
10
Nick Evans

لحل مشكلة الحصول على الرقم بدلاً من النص باستخدام طريقة تمديد Prise.

public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
{
  var values = from TEnum e in Enum.GetValues(typeof(TEnum))
               select new { ID = (int)Enum.Parse(typeof(TEnum),e.ToString())
                         , Name = e.ToString() };

  return new SelectList(values, "Id", "Name", enumObj);
}
10
ceedee

هناك طريقة سهلة للغاية لإنجاز هذا - دون كل عناصر الامتداد التي تبدو مبالغة:

التعداد الخاص بك:

    public enum SelectedLevel
    {
       Level1,
       Level2,
       Level3,
       Level4
    }

داخل وحدة التحكم الخاصة بك ربط التعداد بقائمة:

    List<SelectedLevel> myLevels = Enum.GetValues(typeof(SelectedLevel)).Cast<SelectedLevel>().ToList();

بعد ذلك قم برميها في ViewBag:

    ViewBag.RequiredLevel = new SelectList(myLevels);

أخيرًا ، اربطها مع طريقة العرض:

    @Html.DropDownList("selectedLevel", (SelectList)ViewBag.RequiredLevel, new { @class = "form-control" })

هذه هي أسهل طريقة وجدت إليها ولا تتطلب أي امتدادات أو أي شيء مجنون.

UPDATE: انظر تعليق أندروز أدناه.

9
Louie Bacaj

تريد إلقاء نظرة على استخدام شيء مثل Enum.GetValues

8
Garry Shutler
@Html.DropDownListFor(model => model.Type, Enum.GetNames(typeof(Rewards.Models.PropertyType)).Select(e => new SelectListItem { Text = e }))
7
Mr. Pumpkin

هذه هي إجابات Rune & Prize التي تم تغييرها لاستخدام قيمة التعداد int كمعرّف.

التعداد عينة:

public enum ItemTypes
{
    Movie = 1,
    Game = 2,
    Book = 3
}

طريقة التمديد:

    public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
    {
        var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                     select new { Id = (int)Enum.Parse(typeof(TEnum), e.ToString()), Name = e.ToString() };

        return new SelectList(values, "Id", "Name", (int)Enum.Parse(typeof(TEnum), enumObj.ToString()));
    }

عينة من الاستخدام:

 <%=  Html.DropDownList("MyEnumList", ItemTypes.Game.ToSelectList()) %>

تذكر أن تستورد مساحة الاسم التي تحتوي على طريقة الامتداد

<%@ Import Namespace="MyNamespace.LocationOfExtensionMethod" %>

عينة من HTML ولدت:

<select id="MyEnumList" name="MyEnumList">
    <option value="1">Movie</option>
    <option selected="selected" value="2">Game</option>
    <option value="3">Book </option>
</select>

لاحظ أن العنصر الذي تستخدمه للاتصال بـ ToSelectList هو العنصر المحدد.

6
Mr. Flibble

هذا هو الإصدار للحلاقة:

@{
    var itemTypesList = new List<SelectListItem>();
    itemTypesList.AddRange(Enum.GetValues(typeof(ItemTypes)).Cast<ItemTypes>().Select(
                (item, index) => new SelectListItem
                {
                    Text = item.ToString(),
                    Value = (index).ToString(),
                    Selected = Model.ItemTypeId == index
                }).ToList());
 }


@Html.DropDownList("ItemTypeId", itemTypesList)
5
user550950

الآن ، يتم دعم هذه الميزة خارج الإطار في MVC 5.1 حتى @Html.EnumDropDownListFor()

تحقق من الرابط التالي:

https://docs.Microsoft.com/en-us/aspnet/mvc/overview/releases/mvc51-release-notes#Enum

إنه لأمر مخز حقًا أن الأمر استغرق تطبيق Microsoft 5 سنوات مثل الميزة المطلوبة بشدة وفقًا للتصويت أعلاه!

5
Lafi

حسنًا ، لقد تأخرت كثيرًا عن الحفلة ، لكن لما يستحق الأمر ، فقد قمت بالتدوين حول هذا الموضوع بالذات ، حيث أقوم بإنشاء فصل EnumHelper الذي يتيح تحويلاً سهلاً للغاية.

http://jnye.co/Posts/4/creating-a-dropdown-list-from-an-enum-in-mvc-and-c٪23

في وحدة التحكم الخاصة بك:

//If you don't have an enum value use the type
ViewBag.DropDownList = EnumHelper.SelectListFor<MyEnum>();

//If you do have an enum value use the value (the value will be marked as selected)    
ViewBag.DropDownList = EnumHelper.SelectListFor(MyEnum.MyEnumValue);

في طريقة العرض الخاصة بك:

@Html.DropDownList("DropDownList")
@* OR *@
@Html.DropDownListFor(m => m.Property, ViewBag.DropDownList as SelectList, null)

فئة المساعد:

public static class EnumHelper
{
    // Get the value of the description attribute if the   
    // enum has one, otherwise use the value.  
    public static string GetDescription<TEnum>(this TEnum value)
    {
        var fi = value.GetType().GetField(value.ToString());

        if (fi != null)
        {
            var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

            if (attributes.Length > 0)
            {
                return attributes[0].Description;
            }
        }

        return value.ToString();
    }

    /// <summary>
    /// Build a select list for an enum
    /// </summary>
    public static SelectList SelectListFor<T>() where T : struct
    {
        Type t = typeof(T);
        return !t.IsEnum ? null
                         : new SelectList(BuildSelectListItems(t), "Value", "Text");
    }

    /// <summary>
    /// Build a select list for an enum with a particular value selected 
    /// </summary>
    public static SelectList SelectListFor<T>(T selected) where T : struct
    {
        Type t = typeof(T);
        return !t.IsEnum ? null
                         : new SelectList(BuildSelectListItems(t), "Text", "Value", selected.ToString());
    }

    private static IEnumerable<SelectListItem> BuildSelectListItems(Type t)
    {
        return Enum.GetValues(t)
                   .Cast<Enum>()
                   .Select(e => new SelectListItem { Value = e.ToString(), Text = e.GetDescription() });
    }
}
4
NinjaNye

بناءً على إجابة Simon ، هناك طريقة مماثلة تتمثل في الحصول على قيم Enum لعرضها من ملف Resource ، بدلاً من سمة وصف داخل Enum نفسها. يعد هذا مفيدًا إذا كان موقعك يحتاج إلى تقديم بأكثر من لغة واحدة ، وإذا كنت تريد أن يكون لديك ملف مورد محدد لـ Enums ، فيمكنك التقدم خطوة واحدة والحصول على قيم Enum فقط ، في التعداد الخاص بك وإحالتها من الإضافة بواسطة اصطلاح مثل [EnumName] _ [EnumValue] - في النهاية أقل كتابة!

التمديد ثم يبدو:

public static IHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> html, Expression<Func<TModel, TEnum>> expression)
{            
    var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);

    var enumType = Nullable.GetUnderlyingType(metadata.ModelType) ?? metadata.ModelType;

    var enumValues = Enum.GetValues(enumType).Cast<object>();

    var items = from enumValue in enumValues                        
                select new SelectListItem
                {
                    Text = GetResourceValueForEnumValue(enumValue),
                    Value = ((int)enumValue).ToString(),
                    Selected = enumValue.Equals(metadata.Model)
                };


    return html.DropDownListFor(expression, items, string.Empty, null);
}

private static string GetResourceValueForEnumValue<TEnum>(TEnum enumValue)
{
    var key = string.Format("{0}_{1}", enumValue.GetType().Name, enumValue);

    return Enums.ResourceManager.GetString(key) ?? enumValue.ToString();
}

الموارد في ملف Enums.Resx تبدو وكأنها ItemTypes_Movie: Film

شيء آخر أود القيام به هو ، بدلاً من استدعاء طريقة الامتداد مباشرةً ، أفضل أن أسميها باستخدام @ Html.EditorFor (x => x.MyProperty) ، أو من الناحية المثالية فقط أن يكون النموذج بأكمله ، بنسخة واحدة @ Html.EditorForModel (). للقيام بذلك ، أقوم بتغيير قالب السلسلة لتبدو هكذا

@using MVCProject.Extensions

@{
    var type = Nullable.GetUnderlyingType(ViewData.ModelMetadata.ModelType) ?? ViewData.ModelMetadata.ModelType;

    @(typeof (Enum).IsAssignableFrom(type) ? Html.EnumDropDownListFor(x => x) : Html.TextBoxFor(x => x))
}

إذا كان هذا يهمك ، فقد وضعت إجابة أكثر تفصيلاً هنا على مدونتي:

http://paulthecyclist.com/2013/05/24/enum-dropdown/

4
PaulTheCyclist

لقد تأخرت كثيرًا عن هذه الخطوة ، لكنني وجدت طريقة رائعة جدًا للقيام بذلك من خلال سطر واحد من الكود ، إذا كنت سعيدًا بإضافة حزمة ميلودي غير المقيدة NuGet (مكتبة صغيرة لطيفة من Jon Skeet).

هذا الحل أفضل لأنه:

  1. إنه يضمن (مع قيود النوع العام) أن القيمة هي حقا قيمة التعداد (بسبب لحن غير مقيد)
  2. إنه يتجنب الملاكمة غير الضرورية (بسبب ميلودي غير المقيد)
  3. يقوم بتخزين جميع الأوصاف لتفادي استخدام التفكير في كل مكالمة (بسبب ميلودي غير المقيد)
  4. إنه رمز أقل من الحلول الأخرى!

لذلك ، إليك الخطوات اللازمة لإنجاز هذا الأمر:

  1. في وحدة التحكم في إدارة الحزم ، "تثبيت حزمة UnconstrainedMelody"
  2. أضف خاصية على النموذج الخاص بك مثل:

    //Replace "YourEnum" with the type of your enum
    public IEnumerable<SelectListItem> AllItems
    {
        get
        {
            return Enums.GetValues<YourEnum>().Select(enumValue => new SelectListItem { Value = enumValue.ToString(), Text = enumValue.GetDescription() });
        }
    }
    

الآن وبعد أن تم كشف كشف SelectListItem على الطراز الخاص بك ، يمكنك استخدام @ Html.DropDownList أو @ Html.DropDownListFor باستخدام هذه الخاصية كمصدر.

3
nootn

في .NET Core ، يمكنك فقط استخدام هذا:

@Html.DropDownListFor(x => x.Foo, Html.GetEnumSelectList<MyEnum>())
3
GoldenAge

يمكنك أيضًا استخدام HtmlHelpers المخصص في Griffin.MvcContrib. الكود التالي:

@Html2.CheckBoxesFor(model => model.InputType) <br />
@Html2.RadioButtonsFor(model => model.InputType) <br />
@Html2.DropdownFor(model => model.InputType) <br />

يولد:

enter image description here

https://github.com/jgauffin/griffin.mvccontrib

2
jgauffin

إذا كنت ترغب في إضافة دعم الترجمة ، فقم فقط بتغيير طريقة s.toString () إلى شيء مثل هذا:

ResourceManager rManager = new ResourceManager(typeof(Resources));
var dayTypes = from OperatorCalendarDay.OperatorDayType s in Enum.GetValues(typeof(OperatorCalendarDay.OperatorDayType))
               select new { ID = s, Name = rManager.GetString(s.ToString()) };

هنا ، typeof (Resources) هو المورد الذي تريد تحميله ، ثم تحصل على السلسلة المترجمة ، وهي مفيدة أيضًا إذا كان العداد الخاص بك يحتوي على قيم بكلمات متعددة.

2
brafales

هذه هي روايتي من طريقة المساعد. انا استعمل هذا:

var values = from int e in Enum.GetValues(typeof(TEnum))
             select new { ID = e, Name = Enum.GetName(typeof(TEnum), e) };

بدلا من ذلك:

var values = from TEnum e in Enum.GetValues(typeof(TEnum))
           select new { ID = (int)Enum.Parse(typeof(TEnum),e.ToString())
                     , Name = e.ToString() };

ها هو:

public static SelectList ToSelectList<TEnum>(this TEnum self) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum)
        {
            throw new ArgumentException("self must be enum", "self");
        }

        Type t = typeof(TEnum);

        var values = from int e in Enum.GetValues(typeof(TEnum))
                     select new { ID = e, Name = Enum.GetName(typeof(TEnum), e) };

        return new SelectList(values, "ID", "Name", self);
    }
2
Vadim Sentiaev

لقد وجدت إجابة هنا . ومع ذلك ، فإن بعض التعدادات الخاصة بي لها سمة [Description(...)] ، لذلك قمت بتعديل الكود لتقديم الدعم لذلك:

    enum Abc
    {
        [Description("Cba")]
        Abc,

        Def
    }


    public static MvcHtmlString EnumDropDownList<TEnum>(this HtmlHelper htmlHelper, string name, TEnum selectedValue)
    {
        IEnumerable<TEnum> values = Enum.GetValues(typeof(TEnum))
            .Cast<TEnum>();

        List<SelectListItem> items = new List<SelectListItem>();
        foreach (var value in values)
        {
            string text = value.ToString();

            var member = typeof(TEnum).GetMember(value.ToString());
            if (member.Count() > 0)
            {
                var customAttributes = member[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
                if (customAttributes.Count() > 0)
                {
                    text = ((DescriptionAttribute)customAttributes[0]).Description;
                }
            }

            items.Add(new SelectListItem
            {
                Text = text,
                Value = value.ToString(),
                Selected = (value.Equals(selectedValue))
            });
        }

        return htmlHelper.DropDownList(
            name,
            items
            );
    }

امل ان يساعد.

2
Alkasai

حل آخر لطريقة التمديد هذه - لم يحدد الإصدار الحالي القيمة الحالية للتعداد. لقد حددت السطر الأخير:

public static SelectList ToSelectList<TEnum>(this TEnum enumObj) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum) throw new ArgumentException("An Enumeration type is required.", "enumObj");

        var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                       select new
                       {
                           ID = (int)Enum.Parse(typeof(TEnum), e.ToString()),
                           Name = e.ToString()
                       };


        return new SelectList(values, "ID", "Name", ((int)Enum.Parse(typeof(TEnum), enumObj.ToString())).ToString());
    }
2
justabuzz

أرغب في الإجابة على هذا السؤال بطريقة مختلفة ، حيث لا يحتاج المستخدم إلى فعل أي شيء بتعبير controller أو Linq. من هنا...

لدي ENUM

public enum AccessLevelEnum
    {
        /// <summary>
        /// The user cannot access
        /// </summary>
        [EnumMember, Description("No Access")]
        NoAccess = 0x0,

        /// <summary>
        /// The user can read the entire record in question
        /// </summary>
        [EnumMember, Description("Read Only")]
        ReadOnly = 0x01,

        /// <summary>
        /// The user can read or write
        /// </summary>
        [EnumMember, Description("Read / Modify")]
        ReadModify = 0x02,

        /// <summary>
        /// User can create new records, modify and read existing ones
        /// </summary>
        [EnumMember, Description("Create / Read / Modify")]
        CreateReadModify = 0x04,

        /// <summary>
        /// User can read, write, or delete
        /// </summary>
        [EnumMember, Description("Create / Read / Modify / Delete")]
        CreateReadModifyDelete = 0x08,

        /*/// <summary>
        /// User can read, write, or delete
        /// </summary>
        [EnumMember, Description("Create / Read / Modify / Delete / Verify / Edit Capture Value")]
        CreateReadModifyDeleteVerify = 0x16*/
    }

الآن لا يمكنني إنشاء dropdown باستخدام هذا enum.

@Html.DropDownList("accessLevel",new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum))),new { @class = "form-control" })

OR

@Html.DropDownListFor(m=>m.accessLevel,new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum))),new { @class = "form-control" })

إذا كنت تريد تحديد فهرس ، فجرّب هذا

@Html.DropDownListFor(m=>m.accessLevel,new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum)) , AccessLevelEnum.NoAccess ),new { @class = "form-control" })

لقد استخدمت هنا AccessLevelEnum.NoAccess كمعلمة إضافية لتحديد القائمة المنسدلة بشكل افتراضي.

1
gdmanandamohon
@Html.DropDownListFor(model => model.MaritalStatus, new List<SelectListItem> 
{  

new SelectListItem { Text = "----Select----", Value = "-1" },


new SelectListItem { Text = "Marrid", Value = "M" },


 new SelectListItem { Text = "Single", Value = "S" }

})
1
vicky
@Html.DropdownListFor(model=model->Gender,new List<SelectListItem>
{
 new ListItem{Text="Male",Value="Male"},
 new ListItem{Text="Female",Value="Female"},
 new ListItem{Text="--- Select -----",Value="-----Select ----"}
}
)
1
Shahnawaz

انتهى بي الأمر إلى إنشاء طرق إرشادية لفعل ما هو أساس قبول الإجابة هنا. يتعامل النصف الأخير من Gist مع Enum على وجه التحديد.

https://Gist.github.com/3813767

1
Nick Albrecht

هنا تباين مارتن Faartoft حيث يمكنك وضع علامات مخصصة وهو لطيف للترجمة.

public static class EnumHtmlHelper
{
    public static SelectList ToSelectList<TEnum>(this TEnum enumObj, Dictionary<int, string> customLabels)
        where TEnum : struct, IComparable, IFormattable, IConvertible
    {
        var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                     select new { Id = e, Name = customLabels.First(x => x.Key == Convert.ToInt32(e)).Value.ToString() };

        return new SelectList(values, "Id", "Name", enumObj);
    }
}

استخدام في الرأي:

@Html.DropDownListFor(m => m.Category, Model.Category.ToSelectList(new Dictionary<int, string>() { 
          { 1, ContactResStrings.FeedbackCategory }, 
          { 2, ContactResStrings.ComplainCategory }, 
          { 3, ContactResStrings.CommentCategory },
          { 4, ContactResStrings.OtherCategory }
      }), new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Category)
1
Rushino
        ////  ViewModel

        public class RegisterViewModel
          {

        public RegisterViewModel()
          {
              ActionsList = new List<SelectListItem>();
          }

        public IEnumerable<SelectListItem> ActionsList { get; set; }

        public string StudentGrade { get; set; }

           }

       //// Enum Class

        public enum GradeTypes
             {
               A,
               B,
               C,
               D,
               E,
               F,
               G,
               H
            }

         ////Controller action 

           public ActionResult Student()
               {
    RegisterViewModel vm = new RegisterViewModel();
    IEnumerable<GradeTypes> actionTypes = Enum.GetValues(typeof(GradeTypes))
                                         .Cast<GradeTypes>();                  
    vm.ActionsList = from action in actionTypes
                     select new SelectListItem
                     {
                         Text = action.ToString(),
                         Value = action.ToString()
                     };
              return View(vm);
               }

         ////// View Action

   <div class="form-group">
                            <label class="col-lg-2 control-label" for="hobies">Student Grade:</label>
                            <div class="col-lg-10">
                               @Html.DropDownListFor(model => model.StudentGrade, Model.ActionsList, new { @class = "form-control" })
                            </div>
1
shuvo sarker

في MVC4 ، أود أن أفعل هذا

@Html.DropDownList("RefType", new SelectList(Enum.GetValues(typeof(WebAPIApp.Models.RefType))), " Select", new { @class = "form-control" })

public enum RefType
    {
        Web = 3,
        API = 4,
        Security = 5,
        FE = 6
    }

    public class Reference
    {
        public int Id { get; set; }
        public RefType RefType { get; set; }
    }
1
PAWAN RAJ Shakya

لقد قمت بما يلي ويعمل بنجاح:

  • في view.cshtml:

Model MyModel.cs

@Html.EnumDropDownListFor(m=>m.MyItemType )
  • في النموذج: MyModel.cs

public ItemTypes MyItemType { get; set; }

1
MarwaAhmad

Simon Goldstone: شكرًا على الحل الذي قدمته ، ويمكن تطبيقه بشكل مثالي في حالتي. المشكلة الوحيدة هي أنني اضطررت إلى ترجمتها إلى VB. ولكن الآن يتم ذلك ولتوفير وقت الآخرين (في حالة احتياجهم إليه) ، أضعه هنا:

Imports System.Runtime.CompilerServices
Imports System.ComponentModel
Imports System.Linq.Expressions

Public Module HtmlHelpers
    Private Function GetNonNullableModelType(modelMetadata As ModelMetadata) As Type
        Dim realModelType = modelMetadata.ModelType

        Dim underlyingType = Nullable.GetUnderlyingType(realModelType)

        If Not underlyingType Is Nothing Then
            realModelType = underlyingType
        End If

        Return realModelType
    End Function

    Private ReadOnly SingleEmptyItem() As SelectListItem = {New SelectListItem() With {.Text = "", .Value = ""}}

    Private Function GetEnumDescription(Of TEnum)(value As TEnum) As String
        Dim fi = value.GetType().GetField(value.ToString())

        Dim attributes = DirectCast(fi.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())

        If Not attributes Is Nothing AndAlso attributes.Length > 0 Then
            Return attributes(0).Description
        Else
            Return value.ToString()
        End If
    End Function

    <Extension()>
    Public Function EnumDropDownListFor(Of TModel, TEnum)(ByVal htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TEnum))) As MvcHtmlString
        Return EnumDropDownListFor(htmlHelper, expression, Nothing)
    End Function

    <Extension()>
    Public Function EnumDropDownListFor(Of TModel, TEnum)(ByVal htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TEnum)), htmlAttributes As Object) As MvcHtmlString
        Dim metaData As ModelMetadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData)
        Dim enumType As Type = GetNonNullableModelType(metaData)
        Dim values As IEnumerable(Of TEnum) = [Enum].GetValues(enumType).Cast(Of TEnum)()

        Dim items As IEnumerable(Of SelectListItem) = From value In values
            Select New SelectListItem With
            {
                .Text = GetEnumDescription(value),
                .Value = value.ToString(),
                .Selected = value.Equals(metaData.Model)
            }

        ' If the enum is nullable, add an 'empty' item to the collection
        If metaData.IsNullableValueType Then
            items = SingleEmptyItem.Concat(items)
        End If

        Return htmlHelper.DropDownListFor(expression, items, htmlAttributes)
    End Function
End Module

النهاية يمكنك استخدامه مثل هذا:

@Html.EnumDropDownListFor(Function(model) (model.EnumField))
1
Michal B.

1- قم بإنشاء التعداد الخاص بك

public enum LicenseType
{
    xxx = 1,
    yyy = 2
}

2 - إنشاء فئة الخدمة الخاصة بك

public class LicenseTypeEnumService
    {

        public static Dictionary<int, string> GetAll()
        {

            var licenseTypes = new Dictionary<int, string>();

            licenseTypes.Add((int)LicenseType.xxx, "xxx");
            licenseTypes.Add((int)LicenseType.yyy, "yyy");

            return licenseTypes;

        }

        public static string GetById(int id)
        {

            var q = (from p in this.GetAll() where p.Key == id select p).Single();
            return q.Value;

        }

    }

3 - تعيين ViewBag في وحدة التحكم الخاصة بك

var licenseTypes = LicenseTypeEnumService.GetAll();
ViewBag.LicenseTypes = new SelectList(licenseTypes, "Key", "Value");

4- اربط قائمة DropDownList الخاصة بك

@Html.DropDownList("LicenseType", (SelectList)ViewBag.LicenseTypes)
0
Mirak