在C#中动态创建HTML表

时间:2016-04-07 12:06:02

标签: c# html asp.net

构建HTML表格的方法是否比我现在尝试的方法更有效?

我正在获取一个对象,并且其中包含一些实体列表。所以我需要通过它们中的每一个并首先构建一个单元格,然后将其添加到一行,最后将其添加到表格中。

我正在尝试的事情是完全混乱,有点工作,但它有太多的冗余代码。

private RecordClickHandler gatherRecordClickHandler() {
    return new RecordClickHandler() {

        @Override
        public void onRecordClick(RecordClickEvent event) {
            //Here i want to check if the record is expanded/collapsed
            if(/*expanded check method here*/)
                collapseRecord(event.getRecord());
            else
                expandRecord(event.getRecord());
        }
    };
}

最后我想返回创建的HTML表格的文本版本。 问题是我有比3(BusinessName,SwiftBIC和IBAN)更多的属性,而且我在mailMessageObject中还有一个对象列表,所以代码会很糟糕。

任何人都知道如何以更简单,更清洁的方式解决这个问题?

4 个答案:

答案 0 :(得分:4)

由于我最近开始创建IDisposable类,我认为这对于这个特定任务既有效又容易阅读:

创建一些非常简单的类

    /// <summary>
    /// https://stackoverflow.com/a/36476600/2343
    /// </summary>
    public class Table : IDisposable
    {
        private StringBuilder _sb;

        public Table(StringBuilder sb, string id = "default", string classValue="")
        {
            _sb = sb;
            _sb.Append($"<table id=\"{id}\" class=\"{classValue}\">\n");
        }

        public void Dispose()
        {
            _sb.Append("</table>");
        }

        public Row AddRow()
        {
            return new Row(_sb);
        }

        public Row AddHeaderRow()
        {
            return new Row(_sb, true);
        }

        public void StartTableBody()
        {
            _sb.Append("<tbody>");

        }

        public void EndTableBody()
        {
            _sb.Append("</tbody>");

        }
    }

    public class Row : IDisposable
    {
        private StringBuilder _sb;
        private bool _isHeader;
        public Row(StringBuilder sb, bool isHeader = false)
        {
            _sb = sb;
            _isHeader = isHeader;
            if (_isHeader)
            {
                _sb.Append("<thead>\n");
            }
            _sb.Append("\t<tr>\n");
        }

        public void Dispose()
        {
            _sb.Append("\t</tr>\n");
            if (_isHeader)
            {
                _sb.Append("</thead>\n");
            }
        }

        public void AddCell(string innerText)
        {
            _sb.Append("\t\t<td>\n");
            _sb.Append("\t\t\t"+innerText);
            _sb.Append("\t\t</td>\n");
        }
    }
}

然后您可以使用以下方式定义表格:

StringBuilder sb = new StringBuilder();

using (Html.Table table = new Html.Table(sb))
{
    foreach (var invalidCompany in mailMessageObject.InvalidCompanies)
    {
        using (Html.Row row = table.AddRow())
        {
            row.AddCell(invalidCompany.BusinessName);
            row.AddCell(invalidCompany.SwiftBIC);
            row.AddCell(invalidCompany.IBAN);
        }
    }
}

string finishedTable = sb.ToString();

答案 1 :(得分:2)

这是一种体面的方法,而且只是“它需要什么”#39;输出像HTML一样复杂的东西 - 除非你想用普通的字符串做这件事(如果不是更糟的话,这就像它一样混乱)。

一个改进:不要多次使用相同的单元格对象,您可能会遇到输出错误的风险。改进的代码:

row.Cells.Add(new HtmlTableCell { InnerText = invalidCompany.BusinessName });
row.Cells.Add(new HtmlTableCell { InnerText = invalidCompany.SwiftBIC });
row.Cells.Add(new HtmlTableCell { InnerText = invalidCompany.IBAN });

当然,您也可以创建自己的帮助程序来创建单元格,创建一个充满单元格的行等。还有一些很好的库,例如:见https://www.nuget.org/packages/HtmlTags/

答案 2 :(得分:2)

我想补充史蒂夫哈里斯&#39;回答一个更加内置的类库。他的答案是一个非常优雅的解决方案,使我创建的Windows服务无需参考System.Web就没有充分的理由!

定义的类:

  public static class Html
  {
    public class Table : HtmlBase, IDisposable
    {
      public Table(StringBuilder sb, string classAttributes = "", string id = "") : base(sb)
      {
        Append("<table");
        AddOptionalAttributes(classAttributes, id);
      }

      public void StartHead(string classAttributes = "", string id = "")
      {
        Append("<thead");
        AddOptionalAttributes(classAttributes, id);
      }

      public void EndHead()
      {
        Append("</thead>");
      }

      public void StartFoot(string classAttributes = "", string id = "")
      {
        Append("<tfoot");
        AddOptionalAttributes(classAttributes, id);
      }

      public void EndFoot()
      {
        Append("</tfoot>");
      }

      public void StartBody(string classAttributes = "", string id = "")
      {
        Append("<tbody");
        AddOptionalAttributes(classAttributes, id);
      }

      public void EndBody()
      {
        Append("</tbody>");
      }

      public void Dispose()
      {
        Append("</table>");
      }

      public Row AddRow(string classAttributes = "", string id = "")
      {
        return new Row(GetBuilder(), classAttributes, id);
      }
    }

    public class Row : HtmlBase, IDisposable
    {
      public Row(StringBuilder sb, string classAttributes = "", string id = "") : base(sb)
      {
        Append("<tr");
        AddOptionalAttributes(classAttributes, id);
      }
      public void Dispose()
      {
        Append("</tr>");
      }
      public void AddCell(string innerText, string classAttributes = "", string id = "", string colSpan = "")
      {
        Append("<td");
        AddOptionalAttributes(classAttributes, id, colSpan);
        Append(innerText);
        Append("</td>");
      }
    }

    public abstract class HtmlBase
    {
      private StringBuilder _sb;

      protected HtmlBase(StringBuilder sb)
      {
        _sb = sb;
      }

      public StringBuilder GetBuilder()
      {
        return _sb;
      }

      protected void Append(string toAppend)
      {
        _sb.Append(toAppend);
      }

      protected void AddOptionalAttributes(string className = "", string id = "", string colSpan = "")
      {

        if (!id.IsNullOrEmpty())
        {
          _sb.Append($" id=\"{id}\"");
        }
        if (!className.IsNullOrEmpty())
        {
          _sb.Append($" class=\"{className}\"");
        }
        if (!colSpan.IsNullOrEmpty())
        {
          _sb.Append($" colspan=\"{colSpan}\"");
        }
        _sb.Append(">");
      }
    }
  }

用法:

StringBuilder sb = new StringBuilder();
      using (Html.Table table = new Html.Table(sb, id: "some-id"))
      {
        table.StartHead();
        using (var thead = table.AddRow())
        {
          thead.AddCell("Category Description");
          thead.AddCell("Item Description");
          thead.AddCell("Due Date");
          thead.AddCell("Amount Budgeted");
          thead.AddCell("Amount Remaining");
        }
        table.EndHead();
        table.StartBody();
        foreach (var alert in alertsForUser)
        {
          using (var tr = table.AddRow(classAttributes: "someattributes"))
          {
           tr.AddCell(alert.ExtendedInfo.CategoryDescription);
            tr.AddCell(alert.ExtendedInfo.ItemDescription);
            tr.AddCell(alert.ExtendedInfo.DueDate.ToShortDateString());
            tr.AddCell(alert.ExtendedInfo.AmountBudgeted.ToString("C"));
            tr.AddCell(alert.ExtendedInfo.ItemRemaining.ToString("C"));
          }
        }
        table.EndBody();
      }
      return sb.ToString();

答案 3 :(得分:0)

我想也许你可以添加一个函数来获取你对象的所有属性。然后迭代它们。您还可以创建需要在消息中显示的属性列表。

    private static PropertyInfo[] GetProperties(object obj)
    {
        return obj.GetType().GetProperties();
    }

    // -------
    foreach (var invalidCompany in mailMessageObject.InvalidCompanies)
    {
        var properties = GetProperties(invalidCompany);     
        foreach (var p in properties)
        {   
            string name = p.Name;
            if(propertiesThatNeedToBeDisplayed.Contains(name)
            {
                cell.InnerText = p.GetValue(invalidCompany, null);
                row.Cells.Add(cell);
                table.Rows.Add(row);
            }
        }
    }