2013-08-27 58 views
11

Tôi muốn tạo ra một helper có thể được sử dụng nhưTạo tùy chỉnh Html Helper: MyHelperFor

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

này phải trả lại ví dụ

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

nếu nó là @Html.MyHelperFor(m => m.MailID) này sẽ trả về

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

Tôi có thể truy cập vào tên thuộc tính trong phương thức trợ giúp để tạo loại trình trợ giúp này, tôi nghĩ vậy.

Tôi làm cách nào để thực hiện việc này?

Trả lời

18

Bạn có thể làm một cái gì đó như (sau đây cũng sẽ có các thuộc tính HTML bổ sung).

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

Điều này sẽ được thêm vào bên trong một lớp tĩnh dưới không gian tên * System.Web.Mvc.Html *. – BornToCode

+0

@BornToCode Bạn biết đấy, tôi thích phần mở rộng được viết dưới không gian tên của kiểu mà chúng tham chiếu, nếu không các nhà phát triển khác không bao giờ sử dụng chúng nếu họ không biết chúng vì chúng cần biết về chúng và không gian tên mà chúng sống để thêm tham chiếu và sử dụng nó. – mattytommo

+0

Câu hỏi được yêu cầu cho dữ liệu-something = "MailID" nơi bạn đặt nó thành "cái gì đó".Ví dụ này cần hiển thị cách nhận giá trị của biểu thức, không chỉ tên của thuộc tính. – xr280xr

2

Điều này sẽ giúp bạn bắt đầu. Hàm này trả về trực tiếp tên thuộc tính nhưng bạn có thể chuyển đổi nó thành phần mở rộng mà bạn đang tìm kiếm với một công việc nhỏ. Ví dụ này có chữ ký phương thức chính xác và lệnh gọi hàm ExpressionHelper để lấy tên thuộc tính của bạn.

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 này đã giúp tôi –

5

Bạn có thể sử dụng phương pháp FromLambaExpression từ ModelMetadata như thế này:

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

Các ModelMetadata lớp trong không gian tên System.Web.Mvc. Phương pháp FromLambdaExpression là những gì được xây dựng trong người trợ giúp sử dụng vì vậy sau đó bạn có thể chắc chắn helper của bạn sẽ hoạt động giống như được xây dựng trong người giúp đỡ. Bằng cách đặt lớp CustomHelpers vào không gian tên System.Web.Mvc.Html, sau đó bạn có thể truy cập trợ giúp của bạn giống như những người giúp đỡ khác, tức là @Html.MyHelperFor().

1

Theo dõi về câu trả lời mattytommo, điều này hoạt động tuyệt vời nhưng chỉ có một vấn đề nhỏ khi được sử dụng với các đối tượng phức tạp, chẳng hạn như nếu bạn đang sử dụng mã này cho một tài sản bên trong một EditorTemplate.

Thay vì

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

Nếu sử dụng MVC4, bạn có thể thay đổi nó để

var propertyName = helper.NameFor(expression); 

hoặc cho MVC3 và dưới

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

Full mã:

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