2016-04-07 18 views
3

私が今行っているHTMLテーブルよりも効率的なHTMLテーブルを構築できますか?C#で動的にHTMLテーブルを作成

私はオブジェクトを取得しており、その中にはエンティティのリストがいくつかあります。だから私はそれらのそれぞれを通過し、最初にセルを構築し、それを行に追加し、最後にテーブルに追加する必要があります。

私が試していることは、まったく面倒な、仕事の種類ですが、余分なコードが多すぎます。

public static string CreateNotificationMailMessage(NotificationMailMessage mailMessageObject) 
{ 
    var table = new HtmlTable(); 
    var mailMessage = new StringBuilder(); 
    string html; 

    if (mailMessageObject.InvalidCompanies.Any()) 
    { 
     HtmlTableRow row; 
     HtmlTableCell cell; 

     foreach (var invalidCompany in mailMessageObject.InvalidCompanies) 
     { 
      row = new HtmlTableRow(); 
      cell = new HtmlTableCell(); 
      cell.InnerText = invalidCompany.BusinessName; 
      row.Cells.Add(cell); 
      cell.InnerText = invalidCompany.SwiftBIC; 
      row.Cells.Add(cell); 
      cell.InnerText = invalidCompany.IBAN; 
      row.Cells.Add(cell); 
      table.Rows.Add(row); 
     } 
    } 
    using (var sw = new StringWriter()) 
    { 
     table.RenderControl(new HtmlTextWriter(sw)); 
     html = sw.ToString(); 
    } 

    mailMessage.AppendFormat(html); 
    return mailMessage.ToString(); 
} 

最終的に、作成したHTMLテーブルのテキスト版を返送したいと思います。 問題は、3(BusinessName、SwiftBIC、IBAN)よりもはるかに多くのプロパティがあり、mailMessageObjectの内部にもう1つのオブジェクトリストがあるため、コードがひどくなるということです。

誰もがこれをより簡単でクリーンな方法で解決する方法を知っていますか?

+0

はあなたがHTMLを生成するためのSystem.Web.Mvc' 'の' TagBuilder'を使用しようとしましたか?私はMVCアプリケーションではなく、単にSystem.Web.Mvcのリファレンスを含んでいます。 –

+0

"。問題は、3(BusinessName、SwiftBIC、IBAN)よりもはるかに多くのプロパティがあることです。"リフレクションのユースケースが可能であり、 'これをHTMLテーブルに含める'というカスタムタグがあります。または、リストをXmlSerializeし、ビューア上でxsltトランスフォームとして変換をHTMLテーブルに残しますか? – tolanj

+0

また、少なくとも2つのことがあると思います(「たくさんのフィールド/プロパティを繰り返し処理するにはどうすればよいですか」)> Reflection、おそらく&与えられたワークセットすべての答えはhtmlのように見えるので、もしあなたが疑問に思うのであれば、実際は反復についてですが、ちょっとした説明が必要かもしれません。 – tolanj

答えて

1

普通の文字列を使っていない限り、それはHTMLと同じように何かを出力するのにまともなアプローチです(これは悪くなくても面倒です)。

1つの改善:同じセルオブジェクトを複数回使用しないでください。出力が不正確になる危険性があります。改善されたコード:もちろん

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/を参照してください。

+0

@PetereB私はあなたのアプローチがとても好きです.HTMLを動的に構築することは常に面倒なことですが、もう1つの質問。 1つのビルドが完了したときに、新しい行に移動するコードではどう思いますか?このコードはforeachループになり、確実に行が少なくなります。今のところ彼らはテーブルの中で一つの大きな列として出てきます。この方法で新しいを追加する方法をいくつか言い表すことはできますか? –

+0

毎回 '新しいHtmlTableRow()'を使用しているかどうかを確認してください。実際のコードと質問が異なる場合があります。また、私の答えに加えて参照してください。 –

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); 
      } 
     } 
    } 
2

私は最近、IDisposableインタークラスを作成するに遊びに来たように、私は、これがこの特定のタスクのための効率的、かつ、より読みやすいの両方だと思う:

いくつかの非常に単純なクラス

を作成します。
public static class Html 
{ 
    public class Table : IDisposable 
    { 
     private StringBuilder _sb; 
     public Table(StringBuilder sb) 
     { 
      _sb = sb; 
      _sb.Append("<table>"); 
     } 
     public void Dispose() 
     { 
      _sb.Append("</table>"); 
     } 
     public Row AddRow() 
     { 
      return new Row(_sb); 
     } 
    } 
    public class Row : IDisposable 
    { 
     private StringBuilder _sb; 
     public Row(StringBuilder sb) 
     { 
      _sb = sb; 
      _sb.Append("<tr>"); 
     } 
     public void Dispose() 
     { 
      _sb.Append("</tr>"); 
     } 
     public void AddCell(string innerText) 
     { 
      _sp.Append("<td>"); 
      _sp.Append(innerText); 
      _sp.Append("</td>"); 
     } 
    } 
} 

次に、あなたが使用してテーブルを定義することができます

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(); 
+0

素晴らしいアイデアスティーブ!私はあなたのクラス定義を補足して、私の答えでもう少しそれを構築しました。 –

0

私はちょうど李だろうSteve Harrisの答えを少し補強するクラスライブラリで補うことはできません。彼の答えは、私が作成していた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(); 
関連する問題