Frage

Wie kann ich eine Standard-Editor Vorlage für Aufzählungen machen? Damit meine ich: Ich kann etwas tun, wie folgt aus:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Enum>" %> 
<% -- any code to read the enum and write a dropdown -->

Und setzen diese in den EditorTemplates Ordner unter dem Namen Enum.ascx?

Hier ist eine Abhilfe für mein Problem, dass ich versuchte, aber es ist nicht das, was ich brauche.

Hier ist meine Enum:

public enum GenderEnum
{
    /// <summary>
    /// Male
    /// </summary>
    [Description("Male Person")]
    Male,

    /// <summary>
    /// Female
    /// </summary>
    [Description("Female Person")]
    Female
}

Ich habe eine Vorlage namens GenderEnum.acsx und steckte es in den Shared/EditorTemplates Ordner. Hier ist die Vorlage:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<AlefTech.HumanResource.Core.GenderEnum>" %>
<%@ Import Namespace="AlefTech.HumanResource.WebModule.Classes" %>
<%=Html.DropDownListFor(m => m.GetType().Name, Model.GetType()) %>

Natürlich Methode ist meine eigene:

public static class HtmlHelperExtension
    {
        public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, Type enumType)
        {
            List<SelectListItem> list = new List<SelectListItem>();
            Dictionary<string, string> enumItems = enumType.GetDescription();
            foreach (KeyValuePair<string, string> pair in enumItems)
                list.Add(new SelectListItem() { Value = pair.Key, Text = pair.Value });
            return htmlHelper.DropDownListFor(expression, list);
        }

        /// <summary>
        /// return the items of enum paired with its descrtioption.
        /// </summary>
        /// <param name="enumeration">enumeration type to be processed.</param>
        /// <returns></returns>
        public static Dictionary<string, string> GetDescription(this Type enumeration)
        {
            if (!enumeration.IsEnum)
            {
                throw new ArgumentException("passed type must be of Enum type", "enumerationValue");
            }

            Dictionary<string, string> descriptions = new Dictionary<string, string>();
            var members = enumeration.GetMembers().Where(m => m.MemberType == MemberTypes.Field);

            foreach (MemberInfo member in members)
            {
                var attrs = member.GetCustomAttributes(typeof(DescriptionAttribute), false);
                if (attrs.Count() != 0)
                    descriptions.Add(member.Name, ((DescriptionAttribute)attrs[0]).Description);
            }
            return descriptions;
        }

    }

Allerdings, auch wenn dies für mich gearbeitet, ist es nicht, was ich frage. Stattdessen muss ich folgendes zu arbeiten:

-Code für Shared\EditorTemplates\Enum.acsx:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Enum>" %>
<%@ Import Namespace="System.Web.Mvc.Html" %>
<%@ Import Namespace="WhereMyExtentionMethod" %>
<%=Html.DropDownListFor(m => m.GetType().Name, Model.GetType()) %>

Damit würde ich nicht eine Vorlage für jeden Enum mehr machen.

War es hilfreich?

Lösung 2

Vielen Dank für Ihre Beiträge
Yngvebn, habe ich versucht, Ihre Lösung (in Ihrem letzten Kommentar) vor, aber das einzige, was ich nicht tat, ist die <dynamic>, benutzte ich in generischer Typ anstelle <Enum>.

zuletzt die Lösung ist:
erstellen Sie eine Vorlage mit dem Namen Enum.acsx und legte es unter den Views \ Shared \ EditorTemplates

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>
<%@ Import Namespace="System.Web.Mvc.Html" %>
<%@ Import Namespace="the extension methods namespace" %>
<% Enum model = (Enum)Model; %>
<%=Html.DropDownList(model.GetType().Name,model.GetType())%>

und in Ihrem Unternehmen:

public class Person
{
  [UIHint("Enum")]
  public GenderEnum Gender{get;set;}
}

public Enum GenderEnum
{
 [Description("Male Person")]
 Male,
 [Description("Female Person")]
 Female
}

und wieder gibt es Extention Methoden:

public static class HtmlHelperExtension
    {
        public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, Type enumType)
        {
            List<SelectListItem> list = new List<SelectListItem>();
            Dictionary<string, string> enumItems = enumType.GetDescription();
            foreach (KeyValuePair<string, string> pair in enumItems)
                list.Add(new SelectListItem() { Value = pair.Key, Text = pair.Value });
            return htmlHelper.DropDownListFor(expression, list);
        }

        /// <summary>
        /// return the items of enum paired with its descrtioption.
        /// </summary>
        /// <param name="enumeration">enumeration type to be processed.</param>
        /// <returns></returns>
        public static Dictionary<string, string> GetDescription(this Type enumeration)
        {
            if (!enumeration.IsEnum)
            {
                throw new ArgumentException("passed type must be of Enum type", "enumerationValue");
            }

            Dictionary<string, string> descriptions = new Dictionary<string, string>();
            var members = enumeration.GetMembers().Where(m => m.MemberType == MemberTypes.Field);

            foreach (MemberInfo member in members)
            {
                var attrs = member.GetCustomAttributes(typeof(DescriptionAttribute), false);
                if (attrs.Count() != 0)
                    descriptions.Add(member.Name, ((DescriptionAttribute)attrs[0]).Description);
            }
            return descriptions;
        }

    }

Andere Tipps

Späte zu beantworten, aber ich hoffe, dass diese anderen hilft. Im Idealfall möchten Sie alle Aufzählungen Ihre Enum-Vorlage per Konvention verwenden, nicht durch eine UIHint jedes Mal spezifiziert, und Sie können das erreichen, indem ein benutzerdefiniertes Modell Metadaten-Anbieter wie folgt zu erstellen:

using System;
using System.Collections.Generic;
using System.Web.Mvc;

public class CustomMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName) {
        var mm = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
        if (modelType.IsEnum && mm.TemplateHint == null) {
            mm.TemplateHint = "Enum";
        }
        return mm;
    }
}

registrieren Sie dann einfach in der Application_Start Methode von Global.asax.cs:

ModelMetadataProviders.Current = new CustomMetadataProvider();

Jetzt sind alle Ihre Enum-Eigenschaften werden Ihre Enum-Vorlage als Standard verwenden.

Hier ist ein Helfer ich dafür gemacht .. Ihrer Ansicht nach können Sie einfach tun:

<%= Html.DropDownForEnum<MyEnum>("some-name-for-dropdown", MyEnum.TheFirstValue) %>

für den Text in der aktuellen Auswahl es für eine Ressource in der Ressource-Datei sucht, die den Namen des ENUM, da sie sonst schreiben Sie einfach den eigentlichen Enumtext selbst.

public static MvcHtmlString DropDownForEnum<T>(this HtmlHelper h, string name, T selectedValue)
{
    Type enumType = typeof(T);
    Tag t = new Tag("select").With("name", name).And("id", name);

    foreach (T val in Enum.GetValues(enumType))
    {
        string enumText = Resources.ResourceManager.GetString(val.ToString());
        if (String.IsNullOrEmpty(enumText)) enumText = val.ToString();
        Tag option = new Tag("option").With("value", (val).ToString()).AndIf(val.Equals(selectedValue), "selected", "selected").WithText(enumText);
        t.Append(option);
    }
    return MvcHtmlString.Create(t.ToString());
}

Sie werden auch meine überladene Tag-Klasse benötigen, wenn Sie es an die Arbeit ohne Umschreiben ..

wollen
public class Tag : TagBuilder
{
public Tag (string TagName): base(TagName)
{

}

public Tag Append(Tag innerTag)
{
    base.InnerHtml += innerTag.ToString();
    return this;
}

public Tag WithText(string text)
{

    base.InnerHtml += text;
    return this;
}

public Tag With(Tag innerTag)
{
    base.InnerHtml = innerTag.ToString();
    return this;
}

public Tag With(string attributeName, string attributeValue)
{
    base.Attributes.Add(attributeName, attributeValue);
    return this;
}

public Tag And(string attributeName, string attributeValue)
{
    base.Attributes.Add(attributeName, attributeValue);
    return this;
}


public Tag AndIf(bool condition, string attributeName, string attributeValue)
{
    if(condition)
        base.Attributes.Add(attributeName, attributeValue);
    return this;
}
}

Nour Sabony, modifizierte ich Ihre Version auch die Unterstützung Lokalisierung mit Ressourcen. Deshalb änderte ich die Description zum DisplayAttribute des DataAnnotations Namespace

    public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, Type enumType)
    {
        List<SelectListItem> list = new List<SelectListItem>();
        Dictionary<string, string> enumItems = enumType.GetDisplayNames(htmlHelper.ViewContext.HttpContext);
        foreach (KeyValuePair<string, string> pair in enumItems)
            list.Add(new SelectListItem() { Value = pair.Key, Text = pair.Value });
        return htmlHelper.DropDownListFor(expression, list);
    }

    /// <summary>
    /// return the items of enum paired with its DisplayName.
    /// </summary>
    /// <param name="enumeration">enumeration type to be processed.</param>
    /// <returns></returns>
    public static Dictionary<string, string> GetDisplayNames(this Type enumeration, HttpContextBase httpContext)
    {
        if (!enumeration.IsEnum)
        {
            throw new ArgumentException("passed type must be of Enum type", "enumerationValue");
        }

        Dictionary<string, string> displayNames = new Dictionary<string, string>();
        var members = enumeration.GetMembers().Where(m => m.MemberType == MemberTypes.Field);

        foreach (MemberInfo member in members)
        {
            var attrs = member.GetCustomAttributes(typeof(DisplayAttribute), false);
            if (attrs.Count() != 0)
                if (((DisplayAttribute)attrs[0]).ResourceType != null)
                {
                    displayNames.Add(member.Name, ((DisplayAttribute)attrs[0]).GetName(););
                }
                else
                {
                    displayNames.Add(member.Name, ((DisplayAttribute)attrs[0]).Name);
                }
        }
        return displayNames;
    }

Die Definition eines Aufzählungs muss wie folgt aussehen jetzt:

public enum Gender
{
    [Display(Name = "Male", ResourceType = typeof(mynamespace.App_LocalResources.Shared))]
    Male = 1,

    [Display(Name = "Female", ResourceType = typeof(mynamespace.App_LocalResources.Shared))]
    Female = 2,

}

kann es in einer Ansicht auf die gleiche Art und Weise verwendet werden, z.B. (Razor):

@Html.DropDownListFor(model => model.Gender, typeof(Gender))

Hope, das hilft jemand!

Ich habe die dropdownlistfor Methode ein wenig einfacher und jetzt können Sie eine selectedValue mit ihm geben:

public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, Type enumType)
{
    return DropDownListFor(htmlHelper, expression, enumType, null);
}

public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, Type enumType, object selectedValue)
{
    Dictionary<string, string> enumItems = enumType.GetDisplayNames(htmlHelper.ViewContext.HttpContext);
    return htmlHelper.DropDownListFor(expression, new SelectList(enumItems, "Key", "Value", selectedValue));
}

Verwenden Sie es wie folgt in Ihrer Ansicht:

@Html.DropDownListFor(m => m.Gender, typeof(Gender), Model.Gender)

Modell ist mein MVC Modell und seine Eigenschaft Geschlecht enthält die selectedValue für die DropDownListFor.

Ich glaube nicht, gibt es eine Standardmethode, einen Editor für alle Aufzählungstypen zu definieren, da Sie unterschiedliche Verhalten abhängig von der Situation wünschen können. Zum Beispiel, vielleicht haben Sie eine [Flags] Enum und Multi wählen möchten, oder Sie wollen ein Dropdownlist, oder wollen Sie Radio-Buttons.

Plus, in der Regel werden Sie irgendeine Art von sinnvoller Anzeige Zeichenfolge wollen über das, was Sie in den Variablennamen Einschränkungen erreichen können.

Sicher Zuordnung , um eine Eigenschaft des Typs Enum arbeitet der Box, aber, wie Sie diesen Wert erhalten wird für Sie sein werden.

Ja

Fast sicher, dass dies funktioniert aus dem Kasten heraus.


Versuchen Sie, Ihre Vorlage den gleichen Namen wie Ihre Enum zu nennen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top