Asp.Net Razor视图传递表达式到局部视图

3

我发现在我的观点中,我经常写下以下内容:

<div class="form-group">
    @Html.LabelFor(x => x.City)
    @Html.EditorFor(x => x.City)
    @Html.ValidationMessageFor(x => x.City)
</div>

我非常希望将这个内容放在一个名为_Field.cshtml的局部视图中,类似于以下示例:
@model //what model type???

<div class="form-group">
    @Html.LabelFor(Model)
    @Html.EditorFor(Model)
    @Html.ValidationMessageFor(Model)
</div>

那么这个函数可以通过以下方式调用:

@Html.Partial("_Field", x => x.City)

如果我想要实现这样的功能,我的部分视图中的@model类型是什么?

更新 这个方法可以工作,但我更愿意使用部分视图来方便地更改模板:

public static MvcHtmlString Field<TModel, TItem>(this HtmlHelper<TModel> html, Expression<Func<TModel, TItem>> expr)
{
  var h = "<div class='form-group'>";
  h += $"{html.LabelFor(expr)}{html.EditorFor(expr)}{html.ValidationMessageFor(expr)}";
  h += "</div>";

  return MvcHtmlString.Create(h);
}
1个回答

3

这是不可能的。然而,你想要的与编辑器模板非常相似。基本上,你只需要在 Views/Shared/EditorTemplates 中创建一个视图,命名方式应该符合以下约定之一:

  • A system or custom type (String.cshtml, Int32.cshtml, MyAwesomeClass.cshtml, etc.)
  • One of the members of the DataType enum (EmailAddress.cshtml, Html.cshtml, PhoneNumber.cshtml, etc.). You would then apply the appropriate DataType attributes to your properties:

    [DataType(DataType.EmailAdress)]
    public string Email { get; set; }
    
  • Any thing you want, in conjunction with the UIHint attribute:

    [UIHint("Foo")]
    public string Foo { get; set; }
    

    Which would then correspond to a Foo.cshtml editor template

在您的观点中,您只需使用 Html.EditorFor

@Html.EditorFor(x => x.City)

那么,举个例子,您可以将Views/Shared/EditorTemplates/String.cshtml设置为:
<div class="form-group">
    @Html.Label("", new { @class = "control-label" })
    @Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = "form-control" })
    @Html.ValidationMessage("")
</div>

(空引号是占位符。Razor会自动填写适当的属性名称,这真是太好了。)

因此调用EditorFor将打印出所有内容,而不仅仅是默认的文本输入。您还可以进一步扩展。如果您有兴趣,我在我的博客上有一些文章(链接)(链接)详细介绍了此方面的内容。

更新

值得一提的是,EditorFor有一些特点:

  1. You can pass a template directly to the call, meaning you can customize what template is used on the fly and per instance:

    @Html.EditorFor(x => x.City, "MyCustomEditorTemplate")
    
  2. You can pass additionalViewData. The members of this anonymous object are added to the ViewData dynamic dictionary. Potentially, you could use this to branch within your editor template to cover additional scenarios. For example:

    @Html.EditorFor(x => x.City, new { formGroup = false })
    

    Then in your editor template:

    @{ var formGroup = ViewData["formGroup"] as bool? ?? true; }
    @if (formGroup)
    {
        <!-- Bootstrap form group -->
    }
    else
    {
        <!-- Just the input -->
    }
    

我考虑使用EditorTemplates,但问题是我在很多地方都使用它们,但并不总是想要它们包装额外的div等,我也不总是想要一个标签。我猜我可以为所有东西创建基于UIHint的模板,并使用_ViewStart来减少HTML。我会再思考一下这个问题。 - mxmissile
请看我上面的更新。这可能会给你一些启示。 - Chris Pratt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接