Reputation: 57957
I have read this excellent Multi-column list article, as well as this question on SO. I've come to the conclusion that there is no cross-browser way to turn a long unordered list into n columns of equal length. So far, I have been reduced to multiple-ul solutions like this:
//Three columns.
string col1 = string.Empty;
string col2 = string.Empty;
string col3 = string.Empty;
int currItem = 0;
int collectionCount = myItemCollection.Count;
foreach item in myItemCollection {
currItem++;
if (currItem < collectionCount * .33)
{
col1 = col1 + item.someProperty
}
else if (currItem < collectionCount * .67)
{
col2 = col2 + item.someProperty
}
else
{
col3 = col3 + item.someProperty
}
}
string allColumns = @"<ul>" + col1 + "</ul><ul>"
col2 + "</ul><ul>" + col3 + "</ul>";
Response.Write(allColumns);
Is there a simpler way to separate my list into groups of three, or better yet, to simply write the appropriate closing/starting ul tags when an element is the last item in a "third"?
Upvotes: 1
Views: 1011
Reputation: 1761
This is too late, but Response.Write will output in an unpredictable place, most likely ahead of all other output.
The "proper" code should be building controls on CreateChildren, Page_Load or any other place:
List<string> items = new List<string>() { "aaa", "bbb", "ccc", "ddd", "eee" };
int colSize = (int)Math.Ceiling(items.Count / 3.0);
HtmlGenericControl ul = null;
for (int i = 0; i < items.Count; i++)
{
if (i % colSize == 0)
{
ul = new HtmlGenericControl("ul");
Page.Form.Controls.Add(ul);
}
HtmlGenericControl li = new HtmlGenericControl("li");
li.InnerText = items[i];
ul.Controls.Add(li);
}
This way you don't need to be concerned about rendering and tracking opening/closing tags.
Upvotes: 1
Reputation: 147401
This is how I personally would choose to implement it.
const int numColumns = 3;
const int numColumns = 3;
var columnLength = (int)Math.Ceiling((double)myItemCollection.Count / 3);
for (int i = 0; i < myItemCollection.Count; i++)
{
if (i % columnLength == 0)
{
if (i > 0)
Response.Write("</ul>");
Response.Write("<ul>");
}
Response.Write(myItemCollection[i].SomeProperty);
}
if (i % columnLength == 0)
Response.Write("</ul>");
You avoid string concatenation altogether (there's really no need when you're just writing to a stream, and if you weren't you'd want to xse StringBuilder
) as well as those nasty floating point operations which could potentially cause inaccuracies for long lists (at the very least they're unnecesary).
Anyway, hope that helps...
Upvotes: 1
Reputation: 91742
If it is an unordered list, you can just float the <li> left and give it a width of a little bit less than (100 / n)%
Upvotes: 0