构建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中还有一个对象列表,所以代码会很糟糕。
任何人都知道如何以更简单,更清洁的方式解决这个问题?
答案 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);
}
}
}