如何让我在剃刀模板中的html助手更可重用?

时间:2011-07-12 22:01:37

标签: c# asp.net-mvc-3 razor

我有一个包含多个地址的表单。商家地址,帐单邮寄地址和送货地址。当然我想使用相同的代码。

我的剃刀模板看起来像这样:

<div class="std-form-line">
    <span class="std-form-no-label"></span>
    @Html.TextBoxFor(x => x.BillingAddress.Line2, new { Class = "optional" })
    @Html.ValidationMessageFor(x => x.BillingAddress.Line2)
</div>
<div class="std-form-line">
    <span class="std-form-no-label"></span>
    @Html.TextBoxFor(x => x.BillingAddress.Line3, new { Class = "optional" })
    @Html.ValidationMessageFor(x => x.BillingAddress.Line3)
</div>
....

渲染时看起来像这样:

<input type="text" value="" name="BillingAddress.Line1" id="BillingAddress_Line1" data-val-required="The Street Address field is required." data-val="true" class="text-box single-line">

现在说我将拥有相同的代码,用于商业和运输,但它看起来像这样:

<div class="std-form-line">
    <span class="std-form-no-label"></span>
      @Html.TextBoxFor(x => x.BusinessAddress.Line2, new { Class = "optional" })
</div>
<div class="std-form-line">
    <span class="std-form-no-label"></span>
      @Html.TextBoxFor(x => x.BusinessAddress.Line3, new { Class = "optional" })
</div>

如何摆脱此代码重复?

3 个答案:

答案 0 :(得分:4)

我这样做的方法是为“地址”创建强类型的显示/编辑模板。

然后拨打@Html.EditorFor(x=>x.BusinessAddress)@Html.DisplayFor(x=>x.BusinessAddress)

您还可以为不同的用途创建不同的模板,然后可选择在Editor / DisplayFor方法中提供模板的名称。

顺便说一下,我提到的模板可能分别位于〜Views / Shared / EditorTemplates或〜Views / Shared / DisplayTemplates文件夹中。或者它们可以驻留在EditorTemplates或DisplayTemplates下的特定Controllers视图文件夹中。

修改:这是一个演示此内容的链接。 Editor Tempates

编辑2 :以下是根据您的评论尝试进一步解释的示例。

地址模型

public partial class Address
{
    public int AddressId { get; set; }
    public string Street1 { get; set; }
    public string Street2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
}

编辑模板:此文件名为“Address.cshtml”,位于我的“〜Views / Shared / EditorTemplates”文件夹中。

@model Address

@Html.HiddenFor(model => model.AddressId)

<div class="editor-label">
    @Html.LabelFor(model => model.Street1)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.Street1)
    @Html.ValidationMessageFor(model => model.Street1)
</div>

<div class="editor-label">
    @Html.LabelFor(model => model.Street2)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.Street2)
    @Html.ValidationMessageFor(model => model.Street2)
</div>

<div class="editor-label">
    @Html.LabelFor(model => model.City)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.City)
    @Html.ValidationMessageFor(model => model.City)
</div>

<div class="editor-label">
    @Html.LabelFor(model => model.State)
</div>
<div class="editor-field">
    @* Populated from Helper *@
    @Html.DropDownListFor(m => m.State, new SelectList(statesDictionary, "Key", "Value"), string.Empty)
    @Html.ValidationMessageFor(model => model.State)
</div>

<div class="editor-label">
    @Html.LabelFor(model => model.Zip)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.Zip)
    @Html.ValidationMessageFor(model => model.Zip)
</div>

创建视图:这是我的视图,它将为我的模型实现编辑器模板。请注意第@Html.EditorForModel();

@model Address

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Address</legend>

        @Html.EditorForModel()

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

现在,如果我的观点模型是其他内容,与“地址”相关联,我会使用@Html.EditorFor(model => model.BusinessAddress)

至于名字,这完全在你的控制之下。默认情况下,它们会映射到您的属性名称,但您可以通过提供包含EditorFor重载中的html属性的对象来更改任何名称。

答案 1 :(得分:1)

在DRY意义上,我没有看到任何重复。如果表单上有3个类似的字段,则标记中需要三个相似的元素。

答案 2 :(得分:1)

为什么不引入AddressType字段?您提到的所有3种地址类型共享相同的字段,只是它们的类型不同;设置每个appart的是AddressType的值。有意义吗?