对数据类型的复杂 html 视图进行标准化的首选方法是什么?

What is the preferred way to standardise complex html views for data types?

我有这样的代码,我在许多 MVC 编辑视图中重复使用。此示例是我们显示复选框的默认方式,但在其他输入类型中也发现了类似的重复。

<div class="form-group">
    @Html.LabelFor(model => model.IsLive, htmlAttributes: new { @class = "control-label col-md-3" })
    <div class="col-md-8 checkbox">
        <div class="col-xs-1">
            @Html.EditorFor(model => model.IsLive)
        </div>
        <div class="col-xs-10">
            @Html.CheckboxLabelFor(model => model.IsLive)
        </div>
    </div>
    <a class="infoonclick col-md-1" title="@Html.DisplayNameFor(model => model.IsLive)" data-content="@Html.DescriptionFor(model => model.IsLive)">
        <span class="fa fa-info-circle"></span>
    </a>
</div>

我想知道 DRY 和标准化的最佳方法是什么?

我想做类似@Html.DefaultCheckboxEditorFor(model => model.IsLive)

的事情

我尝试创建一个自定义的 HtmlHelper,但这似乎涉及太多的硬编码字符串而不是一个好主意。

相反,我觉得我应该为此使用 EditorTemplates,但我不太理解正确的语法。视图的模型是一个布尔值,但我需要获取 属性 特定的内容,例如显示名称和描述。

 @model bool


<div class="form-group">
    @Html.LabelFor(model => model.IsLive, htmlAttributes: new { @class = "control-label col-md-3" })
    <div class="col-md-8 checkbox">
        <div class="col-xs-1">
            @Html.EditorFor(model => model.IsLive)
        </div>
        <div class="col-xs-10">
            @Html.CheckboxLabelFor(model => model.IsLive)
        </div>
    </div>
    <a class="infoonclick col-md-1" title="@Html.DisplayNameFor(model => model.IsLive)" data-content="@Html.DescriptionFor(model => model.IsLive)">
        <span class="fa fa-info-circle"></span>
    </a>
</div>

我有一个项目,我的大部分观点如下所示: (这也适用于多层深层复杂对象,但不适用于任何类型的集合,如 IEnumerable,尽管可以对其进行修改)

<h3>Edit existing page</h3>

<div class="col-xs-12">
    @using (Html.BeginForm("Edit", "Page", FormMethod.Post, new { role = "role" }))
    {
      @Html.EditorForModel()
      <input type="submit" value="Save" class="btn btn-primary" />
    }
</div>

我觉得这很酷。所以模型看起来像:

public class PageEditViewModel
{
    [Editable(false)]
    [DisplayName("Page Id")]
    public Guid Id { get; set; }

    [Editable(false)]
    [DisplayName("Url to resource (format: '/my-resource' or '/sub/resource)'")]
    public string Url { get; set; }

    [Required]
    [MaxLength(50, ErrorMessage = "Maximum Length of 50 Exceeded.")]
    [DisplayName("Title for page (must match Url ex: 'My Resource' or 'Sub Resource'")]
    public string PageTitle { get; set; }

    [MaxLength(int.MaxValue, ErrorMessage = "Content Exceeded Maximum Length")]
    [DataType(DataType.MultilineText)]
    public string Content { get; set; }
}

我有一些编辑器模板:

\Views\Shared\EditorTemplates\multilinetext.cshtml

@model object
@{
  var htmlAttributes = this.ViewData.ModelMetadata.GetHtmlAttributes();
}

<div class="form-group @Html.ErrorClassFor(m => m, "has-error")">
    @Html.LabelFor(m => m, new { @class = "control-label" })
    <div class="controls">
        @Html.TextAreaFor(
            m => m,
            8, 8,
            htmlAttributes)
        @Html.ValidationMessageFor(m => m, null, new { @class = "help-block" })
    </div>
</div>

这一切都神奇地与 object.cshtml 的修改版本一起工作:

@model object

@using System.Text;
@using System.Data;

@{
  ViewDataDictionary viewData = Html.ViewContext.ViewData;
  TemplateInfo templateInfo = viewData.TemplateInfo;
  ModelMetadata modelMetadata = viewData.ModelMetadata;

  System.Text.StringBuilder builder = new StringBuilder();

  string result;

  // DDB #224751
  if (templateInfo.TemplateDepth > 2)
  {
     result = modelMetadata.Model == null ? modelMetadata.NullDisplayText
                                            : modelMetadata.SimpleDisplayText;
  }

  foreach (var prop in modelMetadata.Properties.Where(pm =>
     pm.ShowForEdit
        //&& pm.ModelType != typeof(System.Data.EntityState)
     && !templateInfo.Visited(pm)
     )
     .OrderBy(pm => pm.Order))
  {

     //Type modelType =  Model.GetType();
     Type modelType = modelMetadata.ModelType;
     System.Reflection.PropertyInfo pi = modelType.GetProperty(prop.PropertyName);
     System.ComponentModel.DataAnnotations.DisplayAttribute attribute = pi.GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.DisplayAttribute), false).FirstOrDefault() as System.ComponentModel.DataAnnotations.DisplayAttribute;

     if (attribute != null
         && !string.IsNullOrWhiteSpace(attribute.GetGroupName()))
     {
        //builder.Append(string.Format("<div>{0}</div>", attribute.GetGroupName()));
        builder.Append(Html.Partial("Partial-GroupName", attribute.GetGroupName()));
     }

     builder.Append(Html.Editor(prop.PropertyName, prop.TemplateHint ?? prop.DataTypeName).ToHtmlString());
  }

  result = builder.ToString();
}
@Html.Raw(result)

示例输出:

我的 EditFor 模板是 MacawNL BootstrapEditorTemplates 的版本(我与它没有隶属关系)。