Создание пользовательского помощника Html: 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>
Я должен иметь доступ к имени свойства в вспомогательном методе, чтобы сделать этот тип помощника, я думаю.
Как я могу это сделать?
Ответы
Ответ 1
Вы можете сделать что-то вроде этого (следующие дополнительные атрибуты 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());
}
Ответ 2
Вы можете использовать метод 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()
.
Ответ 3
Это должно помочь вам начать. Эта функция напрямую возвращает имя свойства, но вы должны иметь возможность преобразовать ее в расширение, которое вы ищете, с небольшой работой. В этом примере есть правильная подпись метода и вызов 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);
}
Ответ 4
Следя за ответом 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());
}