Атрибуты бритвы cshtml из словаря в простом элементе html

Я написал помощник, который возвращает атрибуты html в виде словаря, который затем используется любым помощником для отображения атрибутов.

Затем атрибуты используются некоторым кодом javascript.

Код не важен, но вот он

namespace MvcHtmlHelpers
{
    public class PropertyValuePairs<TModel>
    {
        public readonly IDictionary<string, object> Pairs = new Dictionary<string, object>();
        private HtmlHelper<TModel> _html;
        public PropertyValuePairs(HtmlHelper<TModel> html)
        {
            _html=html;
        }
        public PropertyValuePairs<TModel> AddNameFor<TValue>(Expression<Func<TModel, TValue>> expression, object value)
        {
            string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
            string name = _html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(htmlFieldName);
            return AddName(name, value);
        }
        public PropertyValuePairs<TModel> AddName(string name, object value)
        {
            Pairs.Add(name, value);
            return this;
        }
        public PropertyValuePairs<TModel> AddIdFor<TValue>(Expression<Func<TModel, TValue>> expression, object value)
        {
            string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
            string id = _html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName);
            return AddName(id, value);
        }
        public PropertyValuePairs<TModel> AddId(string id, object value)
        {
            Pairs.Add('#' + id, value);
            return this;
        }
    }
    public enum LogicalOperator { And, Or }
    public static class EnabledIfAttributes
    {
        public static PropertyValuePairs<TModel> NewPropertyValues<TModel>(this HtmlHelper<TModel> html)
        {
            return new PropertyValuePairs<TModel>(html);
        }
        //for use in javaScript - lower case property names are intentional
        public class PropertyPair
        {
            public string name { get; set; }
            public object val { get; set; }
        }
        public class dataAttribute
        {
            public string logicalOperator { get; set; }
            public List<PropertyPair> propertyPairs { get; set; }
        }
        public const string ClassName = "enabledif";
        public static string AttributeName = "data-" + ClassName;
        public static IDictionary<string, object> EnabledIfAttributesFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object value)
        {
            return EnabledIfAttributesFor(html, expression, value, new RouteValueDictionary());
        }
        public static IDictionary<string, object> EnabledIfAttributesFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object value, object htmlAttributes)
        {
            return EnabledIfAttributesFor(html, expression, value, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }
        public static IDictionary<string, object> EnabledIfAttributesFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object value, IDictionary<string, object> htmlAttributes)
        {
            var pairList = new PropertyValuePairs<TModel>(html).AddNameFor(expression, value);
            return EnabledIfAttributesFor(html, pairList, new RouteValueDictionary(htmlAttributes));
        }
        public static IDictionary<string, object> EnabledIfAttributesFor<TModel>(this HtmlHelper<TModel> html, PropertyValuePairs<TModel> values, LogicalOperator logicalOperator = LogicalOperator.Or)
        {
            return EnabledIfAttributesFor(html, values, new RouteValueDictionary(), logicalOperator);
        }
        public static IDictionary<string, object> EnabledIfAttributesFor<TModel>(this HtmlHelper<TModel> html, PropertyValuePairs<TModel> values, object htmlAttributes, LogicalOperator logicalOperator = LogicalOperator.Or)
        {
            return EnabledIfAttributesFor(html, values, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes), logicalOperator);
        }
        public static IDictionary<string, object> EnabledIfAttributesFor<TModel>(this HtmlHelper<TModel> html, PropertyValuePairs<TModel> values, IDictionary<string, object> htmlAttributes, LogicalOperator logicalOperator = LogicalOperator.Or)
        {
            //in this case expression refers to other property 
            if (htmlAttributes.ContainsKey("class"))
            {
                string existingClass = htmlAttributes["class"].ToString().Trim();
                htmlAttributes["class"] = existingClass + ' ' + ClassName; 
            }
            else
            {
                htmlAttributes.Add("class",ClassName);
            }

            var attr = new dataAttribute
            {
                logicalOperator = logicalOperator.ToString(),
                propertyPairs = new List<PropertyPair>()
            };

            foreach (var pair in values.Pairs)
            {
                string htmlFieldName = ExpressionHelper.GetExpressionText(pair.Key);
                attr.propertyPairs.Add(new PropertyPair
                {
                    name = html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(htmlFieldName),
                    val = pair.Value
                });
            }

            htmlAttributes.Add(AttributeName, JsonConvert.SerializeObject(attr));
            return htmlAttributes;
        }

    }
}

он используется в коде так

@Html.CheckBoxFor(model => model.AllExclusionCriteriaAbsent, @Html.EnabledIfAttributesFor(model=>model.AllInclusionCriteriaPresent, true))

Я хотел бы добавить те же атрибуты к ‹div›‹/div›, т.е. помощника нет. Написание помощника div глупо, поэтому мне было интересно, существует ли уже существующий метод для отображения словаря в виде атрибутов html (должен быть один, используемый всеми помощниками, которые поставляются с MVC), или способ чисто/сжато сделать это с бритвой 2. Спасибо.

Редактировать

используя предложение Росса, кажется, есть 2 более простых способа приблизиться к этому:

namespace MvcHtmlHelpers
{
    public static class SimpleTagHelper
    {
        public static MvcHtmlString Element(string tagName, IDictionary<string, object> attributes, TagRenderMode renderMode=TagRenderMode.Normal)
        {
            var tag = new TagBuilder(tagName);
            tag.MergeAttributes(attributes);
            return MvcHtmlString.Create(tag.ToString(renderMode));
        }
        public static MvcHtmlString ToAttributes(this IDictionary<string, object> attributeDictionary)
        {
            return MvcHtmlString.Create(string.Join(" ",attributeDictionary.Select(d=>string.Format("{0}=\"{1}\"",d.Key,HttpUtility.HtmlAttributeEncode(d.Value.ToString())))));
        }
    }
}

а затем выберите семантику, которую вы предпочитаете:

@SimpleTagHelper.Element("div", Html.EnabledIfAttributesFor(model => model.AllExclusionCriteriaAbsent, true, new { @class="optionList"}), TagRenderMode.StartTag)

or

<div @Html.EnabledIfAttributesFor(model => model.AllExclusionCriteriaAbsent, true, new { @class="optionList"}).ToAttributes() >

person Brent    schedule 04.06.2013    source источник


Ответы (1)


MVC.Net использует класс TagBuilder (MSDN) во вспомогательных методах Html.

Например. вот код для создания тега Label:

TagBuilder tag = new TagBuilder("label");
tag.SetInnerText(resolvedLabelText);
tag.MergeAttributes(htmlAttributes, replaceExisting: true);
return tag.ToMvcHtmlString(TagRenderMode.Normal);
person Ross McNab    schedule 04.06.2013