2013-08-27 5 views
11

Я хотел бы создать помощник, который может быть использован какСоздания пользовательского Html Helper: MyHelperFor

@Html.MyHelperFor(m => m.Name) 

это должно вернуться к примеру

<span name="Name" data-something="Name"></span>

если @Html.MyHelperFor(m => m.MailID) Это должно вернуться

<span name="MailID" data-something="MailID"></span>

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

Как я могу это сделать?

ответ

18

Вы можете сделать что-то вроде (следующие дополнительные атрибуты HTML тоже).

public static MvcHtmlString MyHelperFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, object htmlAttributes = null) 
{ 
    var data = ModelMetadata.FromLambdaExpression(expression, helper.ViewData); 
    string propertyName = data.PropertyName; 
    TagBuilder span = new TagBuilder("span"); 
    span.Attributes.Add("name", propertyName); 
    span.Attributes.Add("data-something", "something"); 

    if (htmlAttributes != null) 
    { 
     var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes); 
     span.MergeAttributes(attributes); 
    } 

    return new MvcHtmlString(span.ToString()); 
} 
+3

Это должно быть добавлено внутри статического класса в пространстве имен * System.Web.Mvc.Html *. – BornToCode

+0

@BornToCode Вы знаете, я предпочитаю расширения, написанные под пространством имен типа, к которому они относятся, в противном случае другие разработчики никогда не будут использовать их, если они не знают их, поскольку им нужно знать о них и пространстве имен, которое они живите, чтобы добавить ссылку и использовать ее. – mattytommo

+0

Вопрос, заданный для data-something = "MailID", где yours устанавливает его в "something".В этом примере нужно показать, как получить значение выражения, а не только имя свойства. – xr280xr

2

Это должно заставить вас начать. Эта функция напрямую возвращает имя свойства, но вы должны иметь возможность преобразовать ее в расширение, которое вы ищете, с небольшой работой. В этом примере есть правильная сигнатура метода и вызов ExpressionHelper для получения имени вашего свойства.

public static MvcHtmlString MyHelperFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression) 
    { 
     string expressionName = ExpressionHelper.GetExpressionText(expression); 

     return new MvcHtmlString(expressionName); 
    } 
+0

Этот anser помог мне –

5

Вы можете использовать метод FromLambaExpression из ModelMetadata, как это:

namespace System.Web.Mvc.Html 
{ 
    public static class CustomHelpers 
    { 
     public static MvcHtmlString MyHelperFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression) 
     { 
      var metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData); 
      var name = metaData.PropertyName; 
      // create your html string, you could defer to DisplayFor to render a span or 
      // use the TagBuilder class to create a span and add your attributes to it 
      string html = ""; 
      return new MvcHtmlString(html); 
     } 
    } 
} 

ModelMetadata класс находится в System.Web.Mvc пространстве имен. Метод FromLambdaExpression - это то, что используют встроенные помощники, поэтому вы можете быть уверены, что ваш помощник будет функционировать так же, как встроенные помощники. Поместив класс CustomHelpers в пространство имен System.Web.Mvc.Html, вы можете получить доступ к своему помощнику, как и другим помощникам, то есть @Html.MyHelperFor().

1

Вслед за ответ mattytommo, это прекрасно работает, но есть только небольшая проблема при использовании сложных объектов, таких как, если вы используете этот код для свойства помещенного в EditorTemplate.

Вместо

var data = ModelMetadata.FromLambdaExpression(expression, helper.ViewData); 
string propertyName = data.PropertyName; 

При использовании MVC4, вы можете изменить его на

var propertyName = helper.NameFor(expression); 

или MVC3 и ниже

var propertyName = expression.Body.ToString(); 
propertyName = propertyName.Substring(propertyName.IndexOf(".") + 1); 
if (!string.IsNullOrEmpty(helper.ViewData.TemplateInfo.HtmlFieldPrefix)) 
    propertyName = string.Format("{0}.{1}", helper.ViewData.TemplateInfo.HtmlFieldPrefix, propertyName); 

Полный код:

public static MvcHtmlString MyHelperFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, object htmlAttributes = null) 
    { 
     var propertyName = expression.Body.ToString(); 
     propertyName = propertyName.Substring(propertyName.IndexOf(".") + 1); 
     if (!string.IsNullOrEmpty(helper.ViewData.TemplateInfo.HtmlFieldPrefix)) 
      propertyName = string.Format("{0}.{1}", helper.ViewData.TemplateInfo.HtmlFieldPrefix, propertyName); 

     TagBuilder span = new TagBuilder("span"); 
     span.Attributes.Add("name", propertyName); 
     span.Attributes.Add("data-something", propertyName); 

     if (htmlAttributes != null) 
     { 
      var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes); 
      span.MergeAttributes(attributes); 
     } 

     return new MvcHtmlString(span.ToString()); 
    }