簡體   English   中英

使用帶有表達式的現有HtmlHelper的自定義MVC HtmlHelper

[英]Custom MVC HtmlHelper that uses existing HtmlHelpers with Expressions

我正在嘗試制作一個自定義的HtmlHelper,它將在現有HtmlHelper(例如Html.TextBoxForHtml.LabelFor的幫助下生成多個HTML元素。 我遇到的主要問題是,除非將它們全部傳遞到我的自定義HtmlHelper中,否則我將無法創建供這些現有幫助器使用的表達式。 我希望能夠將整個模型傳遞給自定義的HtmlHelper並在幫助器內部創建Expressions並將它們傳遞給現有的。 我正在嘗試以這種方式進行操作,以希望這些屬性仍然可以使用,例如DisplayName的Required和國際化。 這可能嗎?

我知道我可以通過將每個Address屬性通過表達式傳遞到自定義HtmlHelper中來做到這一點,但是它並不像在助手中完成那樣干凈和易於使用。

地址模型

public class Address
{
    [Required(ErrorMessage = "Required"), DisplayName("First Name")]
    public String FirstName { get; set; }

    [Required(ErrorMessage = "Required"), DisplayName("Last Name")]
    public String LastName { get; set; }

    [Required(ErrorMessage = "Required"), DisplayName("Line 1")]
    public String Line1 { get; set; }

    [Required(ErrorMessage = "Required"), DisplayName("Line 2")]
    public String Line2 { get; set; }

    [Required(ErrorMessage = "Required"), DisplayName("City")]
    public String City { get; set; }

    [Required(ErrorMessage = "Required"), DisplayName("State")]
    public String State { get; set; }

    [Required(ErrorMessage = "Required"), DisplayName("Country")]
    public String Country { get; set; }

    [Required(ErrorMessage = "Required"), DisplayName("Postal Code")]
    public String PostalCode { get; set; }
}

自定義HtmlHelper

public static class AddressExtension
{
    public static MvcHtmlString AddressEditorForModel<TModel>(this HtmlHelper<TModel> helper, Address address, String prefix, Boolean showLabels)
    {          
        // There will be more markup in here, this is just slimmed down..

        StringBuilder sb = new StringBuilder();
        sb.AppendLine(String.Format("<div id='{0}_AddressContainer' >", prefix));

        // First Name
        if (showLabels)
            sb.AppendLine(helper.DisplayFor(????).ToString());            
        sb.AppendLine(helper.EditorFor(????).ToString());

        // Last Name
        if (showLabels)
            sb.AppendLine(helper.DisplayFor(????).ToString());            
        sb.AppendLine(helper.EditorFor(????).ToString());

        // Line 1
        if (showLabels)
            sb.AppendLine(helper.DisplayFor(????).ToString());            
        sb.AppendLine(helper.EditorFor(????).ToString());

        // Line 2
        if (showLabels)
            sb.AppendLine(helper.DisplayFor(????).ToString());            
        sb.AppendLine(helper.EditorFor(????).ToString());

        // City
        if (showLabels)
            sb.AppendLine(helper.DisplayFor(????).ToString());            
        sb.AppendLine(helper.EditorFor(????).ToString());

        // State
        if (showLabels)
            sb.AppendLine(helper.DisplayFor(????).ToString());            
        sb.AppendLine(helper.EditorFor(????).ToString());

        // Country
        if (showLabels)
            sb.AppendLine(helper.DisplayFor(????).ToString());            
        sb.AppendLine(helper.EditorFor(????).ToString());

        // Postal Code
        if (showLabels)
            sb.AppendLine(helper.DisplayFor(????).ToString());            
        sb.AppendLine(helper.EditorFor(????).ToString());

        sb.AppendLine("</div>");

        return MvcHtmlString.Create(sb.ToString());
    }

查看(cshtml)

@Html.AddressEditorForModel(Model, "test", true)

您可以使用反射和表達式樹來完成此操作,如下所示:

public static MvcHtmlString AddressEditorForModel<TModel>(this HtmlHelper<TModel> helper, string prefix, bool showLabels)
{          
    // There will be more markup in here, this is just slimmed down..

    StringBuilder sb = new StringBuilder();
    sb.AppendLine(String.Format("<div id='{0}_AddressContainer' >", prefix));

         //Create a parameter expression for the model type
         ParameterExpression paramExpr = Expression.Parameter(typeof (TModel));
         //Loop through the properties you want to create a DisplayFor for
         foreach (var property in typeof (TModel).GetProperties())
         {
             //Create a member access expression for accessing this property
             MemberExpression propertyAccess = Expression.MakeMemberAccess(paramExpr, property);
             //Create the lambda expression (eg. "x => x.Name")
             var lambdaExpr = Expression.Lambda<Func<TModel, string>>(propertyAccess, paramExpr);
             //Pass this lambda to the DisplayFor method
             sb.AppendLine(helper.DisplayFor(lambdaExpr).ToString());

         }

...rest of your method

但是,這假定TModel是您的Address對象,因此您也不必傳遞它。HTML幫助器中的TModel來自強類型視圖,因此,如果您擁有@model類型為Address的視圖,則可以使用上述方法

該視圖將像這樣使用它:

@model Address

@Html.AddressEditorForModel("prefix", true)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM