asp.net - 最新 - mvc c# asp net tutorial




ASP.NET MVCの列挙型からドロップダウンリストを作成するにはどうすればよいですか? (20)

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以下の場合

私はRuneの答えを拡張メソッドに渡しました:

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

私は、 Html.DropDownList拡張メソッドを使用しようとしていますが、列挙でそれを使用する方法を理解できません。

私はこのような列挙を持っているとしましょう:

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

Html.DropDownList拡張メソッドを使用してこれらの値を使用してドロップダウンを作成するにはどうすればよいですか?

または、単にforループを作成し、Html要素を手動で作成するのが最善ですか?


Html.DropDownListForはIEnumerableのみを必要とするため、Prizeのソリューションの代替案は次のとおりです。 これにより簡単に次のように書くことができます:

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

[SelectedItemTypeは、ItemTypes型のモデル上のフィールドで、モデルはnullではありません]

また、typeof(T)ではなくenumValue.GetType()を使用できるので、実際に拡張メソッドを汎用化する必要はありません。

編集:統合されたSimonのソリューションもここに組み込まれ、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();
    }
}

Simonの答えに基づいて、同様のアプローチは、Enum値をEnum自体の記述属性ではなく、リソースファイルから表示することです。 これは、サイトを複数の言語でレンダリングする必要がある場合や、Enumの特定のリソースファイルを使用する場合は、さらに1ステップ進んで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();
}

ItemTypes_Movieのように見えるEnums.Resxファイルのリソース:Film

私が気に入っているもう1つの方法は、拡張メソッドを直接呼び出すのではなく、@ Html.EditorFor(x => x.MyProperty)で呼び出すか、理想的にはフォーム全体を1つの@ 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/


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>()">


ここでは、ローカライゼーションに適したカスタムラベルを置くことができるMartin 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)


これはRazorのバージョンです:

@{
    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)

これはヘルパーメソッドの私のバージョンです。 私はこれを使う:

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

これを達成するための超簡単な方法 - すべての拡張機能を必要とすることなく、

あなたのenum:

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

あなたのコントローラーの中でEnumをリストにバインドする:

    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" })

これは私が見つけた最も簡単な方法であり、拡張機能や狂気のようなものは一切必要ありません。

更新 :以下のAndrewsコメントを参照してください。


より優れたカプセル化ソリューションは次のとおりです。

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

ここにあなたのモデルがあります:

使用例:

生成されたUI:

そして生成されたHTML

ヘルパー拡張ソースコードスナップショット:

サンプルプロジェクトは、私が提供したリンクからダウンロードできます。

編集:ここにコードです:

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

ローカリゼーションサポートを追加する場合は、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)はロードするリソースで、ローカライズされたStringを取得します。また、列挙子が複数の単語を持つ値を持つ場合にも便利です。


私はこれについて党に遅れていることを知っていますが、ドロップダウンで列挙定数ではなく説明的な文字列を使用できるので、このバリアントが有益であるかもしれないと思っていました。 これを行うには、各列挙項目を[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:マイクロソフトではMVC 5.1をリリースしましたが、今はEnumDropDownListFor機能を備えています。 残念ながら、それは[Description]属性を尊重するようには見えないので、上記のコードはまだ成立しています。MVC 5.1のMicrosoftリリースノートのEnumセクションを参照してください。

更新: Display属性[Display(Name = "Sample")]サポートしているので、これを使用できます。

[更新 - ちょうどこれに気づき、コードは、コードの拡張バージョンのように見えます: https://blogs.msdn.microsoft.com/stuartleeks/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums/ : https://blogs.msdn.microsoft.com/stuartleeks/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums/を追加しました。 もしそうなら、帰属は公正に見えるだろう;-)]


私はパーティーに本当に遅れていますが、それが価値あるものであるかどうかについては、非常に簡単な変換を可能にする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() });
    }
}

私は同じ問題にぶつかり、この質問を見つけ、Ashによって提供される解決策は私が探していたものではないと考えました。 HTMLを自分で作成しなければならないということは、組み込みのHtml.DropDownList()関数に比べて柔軟性が低いことを意味します。

C#3などは、これを非常に簡単にします。 TaskStatusという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にします。 犯罪は意図されていない、アッシュ。 :)


私は非常に遅いですが、私はちょうどあなたがUnconstrained Melody NuGetパッケージ(Jon Skeetの素敵な小さなライブラリ)を追加していただければ、1行のコードでこれを行う本当にクールな方法を見つけました。

このソリューションは次の理由により優れています。

  1. 値が実際にenum値であることが保証されています(制約のないメロディのため)
  2. それは不必要なボクシング(拘束されていないメロディのため)
  3. すべての説明をキャッシュして、すべてのコールでリフレクションを使用しないようにします(制約のないメロディによる)
  4. それは他のソリューションより少ないコードです!

そこで、これを実現するための手順は次のとおりです。

  1. パッケージマネージャコンソールで、 "Install-Package 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を使用できます。


@サイモンゴールドストーン:あなたのソリューションをありがとう、それは私の場合に完全に適用することができます。唯一の問題は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))

私はhttps://blogs.msdn.microsoft.com/stuartleeks/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums/答えを見つけた。しかし、私の列挙型の中には[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
            );
    }

希望が役立ちます。


@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" }

})

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




asp.net-mvc