Refactor similar CHTML that renders varying properties using EditorFor and LabelFor

前端 未结 2 1079
北荒
北荒 2020-12-04 02:57

I am building a project with a lot of common code regarding the razor view.

Example:

@Html.LabelFor(model =>
相关标签:
2条回答
  • 2020-12-04 03:11

    You can create a HtmlHelper extension method that will generate all the html for a property, including the label and input element

    using System;
    using System.Linq.Expressions;
    using System.Text;
    using System.Web.Mvc;
    using System.Web.Mvc.Html;
    
    namespace YourAssembly.Html
    {
      public static class BootstrapHelper
      {
        public static MvcHtmlString BootstrapEditorFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression)
        {      
          MvcHtmlString label = LabelExtensions.LabelFor(helper, expression, new { @class = "control-label col-xs-12 col-sm-4 col-md-3" });
          MvcHtmlString editor = EditorExtensions.EditorFor(helper, expression, new { htmlAttributes = new { @class = "form-control" } });
          MvcHtmlString validation = ValidationExtensions.ValidationMessageFor(helper, expression, null, new { @class = "text-danger" });
    
          // Build the input elements
          TagBuilder editorDiv = new TagBuilder("div");
          editorDiv.AddCssClass("col-xs-4 col-sm-2 col-md-2 col-lg-1");
          editorDiv.InnerHtml = editor.ToString();
          // Build the validation message elements
          TagBuilder validationSpan = new TagBuilder("span");
          validationSpan.AddCssClass("help-block");
          validationSpan.InnerHtml = validation.ToString();
          TagBuilder validationDiv = new TagBuilder("div");
          validationDiv.AddCssClass("col-xs-12 col-md-8 col-sm-offset-4 col-md-offset-3");
          validationDiv.InnerHtml = validationSpan.ToString();
          // Combine all elements
          StringBuilder html = new StringBuilder();
          html.Append(label.ToString());
          html.Append(editorDiv.ToString());
          html.Append(validationDiv.ToString());
          // Build the outer div
          TagBuilder outerDiv = new TagBuilder("div");
          outerDiv.AddCssClass("form-group");
          outerDiv.InnerHtml = html.ToString();
          return MvcHtmlString.Create(outerDiv.ToString());
        }
      }
    }
    

    Then you can register this in your web.config file (means you do not need @using ... in the view

    <namespaces>
      <add namespace="System.Web.Mvc" />
      ....
      <add namespace="yourAssembly.Html " /> // add this
    </namespaces>
    

    Now in your main view your can generate all the html shown in your question with just the following 3 lines of code

    @Html.BootstrapEditorFor(m => m.LayoutFrontAmount)
    @Html.BootstrapEditorFor(m => m.LayoutFrontBackAmount)
    @Html.BootstrapEditorFor(m => m.LayoutTRC)
    

    And if you want this to be reusable across multiple projects, compile it in separate dll and add a reference to it in your projects.

    0 讨论(0)
  • 2020-12-04 03:13

    Depends on what the types are for each of LayoutFrontAmount, LayoutFrontBackAmount, and LayoutTRC. Are these all strings? If so, you could have a common view file that stores the template for displaying each, and then display each of them by using @Html.Partial() in your primary view:

    MyView.cshtml

    @model string
    <div class="form-group">
        @Html.LabelFor(model => Model, htmlAttributes: new { @class = "control-label col-xs-12 col-sm-4 col-md-3" })
        <div class="col-xs-4 col-sm-2 col-md-2 col-lg-1">
            @Html.EditorFor(model => Model, new { htmlAttributes = new { @class = "form-control" } })
        </div>
        <div class="col-xs-12 col-md-8 col-sm-offset-4 col-md-offset-3">
            <span class="help-block">@Html.ValidationMessageFor(model => Model, "", new { @class = "text-danger" })</span>
        </div>
    </div>
    

    And then in your main view file you could render each of LayoutFrontAmount, LayoutFrontBackAmount, and LayoutTRC as follows:

    @Html.Partial("MyView", Model.LayoutFrontAmount);
    @Html.Partial("MyView", Model.LayoutFrontBackAmount);
    @Html.Partial("MyView", Model.LayoutTRC);
    

    If they are different types, that poses a bigger challenge.

    0 讨论(0)
提交回复
热议问题