Используя StringBuilder и DataTable, как мне вернуть несколько строк в трех столбцах без разбиения, когда есть только одна строка? - PullRequest
1 голос
/ 21 сентября 2010

У меня есть функция, которая возвращает список адресов электронной почты из хранимого в SQL Proc на основе идентификатора. Он использует StringBuilder и возвращает один столбец. Для большинства идентификаторов есть 4 или менее адресов электронной почты, и этот формат подходит. Однако теперь мы получаем больше идентификаторов с 10+ адресами электронной почты, и это делает страницу слишком длинной.

Функция:

DataTable dt = DAL.ExecStoredProc(DAL.DatabaseName.DB, "storedProc", param);
StringBuilder sb = new StringBuilder();
sb.Append("<br/><br/>");
sb.Append("<table border='0' cellpadding='3'>");
for (int i = 0; i < dt.Rows.Count; i++)
{
    sb.Append("<tr><td>");
    sb.Append(dt.Rows[i]["EMail"].ToString());
    sb.Append("</td></tr>");
}
sb.Append("</table>");
return sb.ToString();

Я попытался использовать следующее, но оно перестало работать, когда слишком мало адресов для возврата:

DataTable dt = DAL.ExecStoredProc(DAL.DatabaseName.DB, "storedProc", param);
StringBuilder sb = new StringBuilder();
sb.Append("<br/><br/>");
sb.Append("<table border='0' cellpadding='3'>");
for (int i = 0; i < dt.Rows.Count; i++)
{
    sb.Append("<tr><td>");
    sb.Append(dt.Rows[i]["EMail"].ToString());
    i++;
    sb.Append("</td>");
    sb.Append("<td>");
    sb.Append(dt.Rows[i]["EMail"].ToString());
    i++;
    sb.Append("</td>");
    sb.Append("<td>");
    sb.Append(dt.Rows[i]["EMail"].ToString());
    i++;
    sb.Append("</td></tr>");
}
sb.Append("</table>");
return sb.ToString();

Ответы [ 3 ]

2 голосов
/ 21 сентября 2010

Вместо создания html-таблицы с помощью строителя строк вы рассматривали возможность использования элемента управления ретранслятора asp.net . Вы можете привязать DataTable непосредственно к повторителю, а затем управлять html из области дизайна html. Это оказалось бы гораздо более гибким для того, что вы пытаетесь сделать. Предполагается, что вы используете asp.net.

Также см. Мой пост о создании настраиваемого элемента управления asp.net, поскольку это даст вам максимальную гибкость и инкапсулирует вашу собственную логику HTML.

Наслаждайтесь!

2 голосов
/ 21 сентября 2010

Используя функцию Linq Take, вы можете заменить следующий блок кода из вашего первого примера:

for (int i = 0; i < dt.Rows.Count; i++)
{
    sb.Append("<tr><td>");
    sb.Append(dt.Rows[i]["EMail"].ToString());
    sb.Append("</td></tr>");
}

с этим:

foreach (var row in dt.Rows.OfType<DataRow>().Take(3))
{
    sb.Append("<tr><td>");
    sb.Append(row["EMail"].ToString());
    sb.Append("</td></tr>");
}

Так как Take возвращает до указанного числа элементов в начале последовательности, этот блок кода будет выполняться от 0 до 3 раз. У вас будет отображаться максимум 3 адреса (даже если их будет больше), и вы не получите IndexOutOfRangeException, если у вас меньше 3.


ОБНОВЛЕНИЕ: совместимо с ASP.NET 2.0

Поскольку вы не можете использовать Linq, результат должен быть таким же:

for (int i = 0; i < (dt.Rows.Count > 3 ? 3 : dt.Rows.Count); i++)
{
    sb.Append("<tr><td>");
    sb.Append(dt.Rows[i]["EMail"].ToString());
    sb.Append("</td></tr>");
}

Выражение dt.Rows.Count > 3 ? 3 : dt.Rows.Count использует оператор ? , чтобы заставить цикл for выполнять итерацию по всем адресам электронной почты, если их больше 3, в этом случае он будет повторяться только 3 раз.

1 голос
/ 21 сентября 2010

Я думаю, Даг находится на правильном пути, но если вы настаиваете на том, чтобы делать это с помощью StringBuilder и цикла for, попробуйте следующее:

DataTable dt = DAL.ExecStoredProc(DAL.DatabaseName.DB, "storedProc", param);

StringBuilder sb = new StringBuilder();
sb.Append("<br/><br/>");
sb.Append("<table border='0' cellpadding='3'>");

string rowFormat = "<tr><td>{0}</td><td>{1}</td><td>{2}</td></tr>";

for (int i = 0; i < dt.Rows.Count; i+=3)
{
    string[] rowEmails = { String.Empty, String.Empty, String.Empty };

    for (int j = 0; j < 3; j++)
    {
        if (i+j < dt.Rows.Count) rowEmails[j] = dt.Rows[i+j]["Email"].ToString();
    }

    sb.AppendFormat(rowFormat, rowEmails[0], rowEmails[1], rowEmails[2]);
}

sb.Append("</table>");

return sb.ToString();
...