【问题标题】:Using display template inside TagBuilder在 TagBuilder 中使用显示模板
【发布时间】:2014-03-17 09:39:56
【问题描述】:

我正在尝试构建一个输出表格行的 HtmlHelper 扩展:

public static MvcHtmlString AddRow(this HtmlHelper helper, string label, params object[]  values)
{
    TagBuilder tdBuilder = new TagBuilder("td");
    tdBuilder.MergeAttribute("colspan", "4");
    tdBuilder.AddCssClass("no-bg");
    TagBuilder divBuilder = new TagBuilder("div");
    divBuilder.AddCssClass("column-label");
    divBuilder.AddCssClass("column-align-left");
    divBuilder.InnerHtml = label;
    tdBuilder.InnerHtml = divBuilder.ToString();

    TagBuilder trBuilder = new TagBuilder("tr");
    trBuilder.InnerHtml = tdBuilder.ToString();

    foreach (var value in values)
    {
        TagBuilder tdValueBuilder = new TagBuilder("td");
        tdValueBuilder.InnerHtml = value.ToString(); // I want to have display template here
        trBuilder.InnerHtml += tdValueBuilder.ToString();
    }

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

虽然这确实正确呈现了行,但它并没有正确格式化所有值(例如 DateTime)。

等效的局部视图可以使用 DisplayFor 方法:

<tr>
<td colspan="4" class="no-bg">
    <div class="column-label column-align-left">
        @Model.Label
    </div>
</td>
@foreach (var value in Model.Values)
{
    <td>
        @Html.DisplayFor(m => value)
    </td>
}

局部视图中的模型是自定义模型,具有标签、列表值等属性。 DisplayFor 使用存在的任何 Display 模板正确呈现值。 那么如何使用 TagBuilder 达到同样的效果呢?

实际的方法有点复杂(带有可选参数和附加逻辑),所以我更喜欢使用 HtmlHelper 扩展。

helper 方法将用于为大型模型的特定属性呈现表行,如下所示:

@Html.AddRow("myLabel1", Model.Foo.Bars.MyValue1)
@Html.AddRow("myLabel2", Model.Foo.MyOtherValue4a, Model.Foo.MyOtherValue4b)
@* etc. *@

【问题讨论】:

  • 你试过 tdValueBuilder.InnerHtml = helper.Display(value); ?
  • @user2900970 helper.Display() 将字符串作为参数,我相信它应该是模型上的属性名称。
  • 对,你为什么不这样用呢?只需为您的模型属性名称期待另一个参数。

标签: asp.net-mvc


【解决方案1】:

通过仔细查看 DisplayFor 帮助程序,我找到了一个可行的解决方案。 解决方案是更改方法以使用与 DisplayFor 帮助器相同的签名,后者使用通用 TModel 和 TValue。

所以我现在拥有的是:

    public static MvcHtmlString AddRowFor<TModel, TValue>(this HtmlHelper<TModel> helper, string label, params Expression<Func<TModel, TValue>>[] values)
    {
        TagBuilder tdBuilder = new TagBuilder("td");
        tdBuilder.MergeAttribute("colspan", "4");
        tdBuilder.AddCssClass("no-bg");
        TagBuilder divBuilder = new TagBuilder("div");
        divBuilder.AddCssClass("column-label");
        divBuilder.AddCssClass("column-align-left");
        divBuilder.InnerHtml = label;
        tdBuilder.InnerHtml = divBuilder.ToString();

        TagBuilder trBuilder = new TagBuilder("tr");
        trBuilder.InnerHtml = tdBuilder.ToString();

        foreach (var value in values)
        {
            TagBuilder tdValueBuilder = new TagBuilder("td");

            // the magic happens here
            var metadata = ModelMetadata.FromLambdaExpression(value, helper.ViewData);
            tdValueBuilder.InnerHtml = helper.DisplayFor(_ => metadata.Model).ToHtmlString();

            trBuilder.InnerHtml += tdValueBuilder.ToString();
        }

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

用法:

@Html.AddRowFor("myLabel1", m => Model.Foo.Bars.MyValue1)
@Html.AddRowFor("myLabel2", m => Model.Foo.MyOtherValue4a, m => Model.Foo.MyOtherValue4b)

唯一仍然困扰我的是我必须引入模型,即使我实际上并没有在辅助方法中使用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多