سؤال

كيف يمكنني عمل قالب محرر افتراضي للعوامل؟ الذي أعني به: هل يمكنني فعل شيء مثل هذا:

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

ووضع هذا في مجلد editortemplates تحت الاسم Enum.ascx?

إليك حلًا عن مشكلتي التي جربتها ، لكن هذا ليس ما أحتاجه.

ها هو التعداد الخاص بي:

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

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

لقد صنعت قالبًا يسمى GenderEnum.acsx ووضعه في Shared/EditorTemplates مجلد. ها هو القالب:

<%@ 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()) %>

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

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

    }

ومع ذلك ، على الرغم من أن هذا نجح بالنسبة لي ، إلا أنه ليس ما أطلبه. بدلاً من ذلك ، أحتاج إلى ما يلي للعمل:

رمز ل 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()) %>

مع هذا ، لن أضطر إلى صنع قالب لكل تعداد بعد الآن.

هل كانت مفيدة؟

المحلول 2

شكرا لكم جميعا على مساهماتكم
Yngvebn ، جربت الحل الخاص بك (في تعليقك الأخير) من قبل ، ولكن الشيء الوحيد الذي لم أفعله هو <dynamic>, ، اعتدت بدلاً من ذلك <Enum> في النوع العام.

أخيرًا ، الحل هو:
قم بإنشاء قالب اسمه enum.acsx ووضعه تحت وجهات النظر مشاركة 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())%>

وفي كيانك:

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

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

ومرة أخرى هناك طرق موسعة:

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

    }

نصائح أخرى

في وقت متأخر للإجابة ولكن آمل أن يساعد هذا الآخرين. من الناحية المثالية ، تريد أن تستخدم جميع التعدادات قالب التعداد الخاص بك عن طريق الاتفاقية ، وليس عن طريق تحديد uihint في كل مرة ، ويمكنك تحقيق ذلك من خلال إنشاء مزود بيانات تعريف نموذجية مثل هذا:

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

ثم قم ببساطة بتسجيله في طريقة application_start من global.asax.cs:

ModelMetadataProviders.Current = new CustomMetadataProvider();

الآن ستستخدم جميع خصائص التعداد الخاصة بك قالب التعداد بشكل افتراضي.

إليك مساعد صنعته لهذا .. في رأيك يمكنك ببساطة القيام به:

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

بالنسبة للنص الموجود في القائمة المنسدلة الفعلية ، سيبحث عن مورد في ملف الموارد الذي يطابق اسم التعداد ، وإلا فقط اكتب التعداد الفعلي نفسه.

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

ستحتاج أيضًا إلى فئة العلامات المفرطة إذا كنت تريد أن تعمل بدون إعادة كتابة ..

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 ، قمت بتعديل نسختك لدعم التوطين مع الموارد. لذلك قمت بتغيير DescriptionAttribut

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

يجب أن يبدو تعريف التعداد هكذا الآن:

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,

}

يمكن استخدامه في عرض بنفس الطريقة ، على سبيل المثال (الحلاقة):

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

أمل أن هذا يساعد شخصاما!

لقد جعلت طريقة DropDownListfor أسهل قليلاً والآن يمكنك إعطاء Value المحدد معها:

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

استخدمه هكذا في وجهة نظرك:

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

النموذج هو طراز MVC الخاص بي وجنسه الذي يحتوي على جنسه المحدد لـ DropDownListfor.

لا أعتقد أن هناك طريقة افتراضية لتحديد محرر لجميع أنواع التعداد لأنك قد ترغب في سلوك مختلف اعتمادًا على الموقف. على سبيل المثال ، ربما يكون لديك [أعلام] التعداد وتريد تحديد متعدد ، أو تريد قائمة منسدلة ، أو تريد أزرار الراديو.

بالإضافة إلى ذلك ، ستحتاج عمومًا إلى نوع من سلسلة العرض ذات مغزى تتجاوز ما يمكنك تحقيقه في قيود التسمية المتغيرة.

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

نعم

تقريبا هذا يعمل خارج الصندوق.


حاول تسمية القالب الخاص بك بنفس اسم التعداد الخاص بك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top