I updated the code to set the top border to a thicker border at the start of each section. I also moved the styling into CSS.
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void GridView1_DataBound(object sender, EventArgs e)
{
string text = "";
int count = 0;
Hashtable ht = new Hashtable();
// loop through all rows to get row counts
foreach (GridViewRow gvr in GridView1.Rows)
{
if (gvr.RowType == DataControlRowType.DataRow)
{
if (gvr.Cells[0].Text == text)
{
count++;
}
else
{
if (count > 0)
{
ht.Add(text, count);
}
text = gvr.Cells[0].Text;
count = 1;
}
}
}
if (count > 1)
{
ht.Add(text, count);
}
// loop through all rows again to set rowspan
text = "";
string currentColor = "altRowStyle";
foreach (GridViewRow gvr in GridView1.Rows)
{
if (gvr.RowType == DataControlRowType.DataRow)
{
if (gvr.Cells[0].Text == text)
{
gvr.Cells.Remove(gvr.Cells[0]);
}
else
{
text = gvr.Cells[0].Text;
count = Int32.Parse(ht[text].ToString());
if (count > 1)
gvr.Cells[0].RowSpan = count;
// Start of new row, alternate color
currentColor = GetRowColor(currentColor);
// If not the first row, set a thicker border
if (gvr.RowIndex > 0)
{
gvr.CssClass += String.Concat(" ", "thickBorder");
}
}
// Set background color
gvr.CssClass += String.Concat(" ", currentColor);
}
}
}
protected string GetRowColor(string originalColor)
{
return (originalColor == "altRowStyle") ? "rowStyle" : "altRowStyle";
}
protected void Page_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt.Columns.Add("this");
dt.Columns.Add("is");
dt.Columns.Add("a");
dt.Columns.Add("test");
DataRow dr = dt.NewRow();
dr["this"] = "data1";
dr["is"] = "data1";
dr["a"] = "data1";
dr["test"] = "data1";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["this"] = "data1";
dr["is"] = "data1";
dr["a"] = "data1";
dr["test"] = "data1";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["this"] = "data1";
dr["is"] = "data1";
dr["a"] = "data1";
dr["test"] = "data1";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["this"] = "data2";
dr["is"] = "data2";
dr["a"] = "data2";
dr["test"] = "data2";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["this"] = "data2";
dr["is"] = "data2";
dr["a"] = "data2";
dr["test"] = "data2";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["this"] = "data3";
dr["is"] = "data3";
dr["a"] = "data3";
dr["test"] = "data3";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["this"] = "data4";
dr["is"] = "data4";
dr["a"] = "data4";
dr["test"] = "data4";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["this"] = "data4";
dr["is"] = "data4";
dr["a"] = "data4";
dr["test"] = "data4";
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["this"] = "data4";
dr["is"] = "data4";
dr["a"] = "data4";
dr["test"] = "data4";
dt.Rows.Add(dr);
GridView1.DataSource = dt;
GridView1.DataBind();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
<style type="text/css">
table.default {
color: #DDD;
text-align: center;
border: 3px solid #333;
}
table.default td {
border-top: 1px solid #CCC;
}
table.default th {
background-color: #333;
}
tr.thickBorder td {
border-top: 3px solid #333;
}
tr.rowStyle {
background-color: Firebrick;
}
tr.altRowStyle {
background-color: DimGray;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<div>
</div>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" OnDataBound="GridView1_DataBound"
GridLines="None" CssClass="default" Width="300px">
<Columns>
<asp:BoundField DataField="This" HeaderText="This" />
<asp:BoundField DataField="Is" HeaderText="Is" />
<asp:BoundField DataField="A" HeaderText="A" />
<asp:BoundField DataField="Test" HeaderText="Test" />
</Columns>
</asp:GridView>
</form>
</body>
</html>
Don't forget to click "Mark as Answer" on the post that helped you. This credits that member, earns you a point and marks your thread as Resolved so everyone will know you have been helped.
The DataBound method should work for any gridview, whatever data source it's bound to. You'll just need to assign a SqlDataSource to the GridView (and remove the Page_Load parts to create the DataTable and bind it to the grid). I included the DataTable
in this example so it could be run as is.
I did find a few bugs that are cleaned up in the version below (with comments on the changes):
protected void GridView1_DataBound(object sender, EventArgs e)
{
// Added reference to the GridView and updated all references
// to use gv instead of GridView1.
GridView gv = (GridView)sender;
string text = "";
int count = 0;
Hashtable ht = new Hashtable();
// loop through all rows to get row counts
foreach (GridViewRow gvr in gv.Rows)
{
if (gvr.RowType == DataControlRowType.DataRow)
{
if (gvr.Cells[0].Text == text)
{
count++;
}
else
{
if (count > 0)
{
ht.Add(text, count);
}
text = gvr.Cells[0].Text;
count = 1;
}
}
}
// Was previously (count > 1), which doesn't cover the last
// row with a unique value
if (count > 0)
{
ht.Add(text, count);
}
// loop through all rows again to set rowspan
text = "";
string currentColor = "altRowStyle";
foreach (GridViewRow gvr in gv.Rows)
{
if (gvr.RowType == DataControlRowType.DataRow)
{
if (gvr.Cells[0].Text == text)
{
gvr.Cells.Remove(gvr.Cells[0]);
}
else
{
text = gvr.Cells[0].Text;
// Related to the count update above, check for null
count = (ht[text] != null) ? Int32.Parse(ht[text].ToString()) : 1;
if (count > 1)
gvr.Cells[0].RowSpan = count;
// Start of new row, alternate color
currentColor = GetRowColor(currentColor);
// If not the first row, set a thicker border
if (gvr.RowIndex > 0)
{
gvr.CssClass += String.Concat(" ", "thickBorder");
}
}
// Set background color
gvr.CssClass += String.Concat(" ", currentColor);
}
}
}
Don't forget to click "Mark as Answer" on the post that helped you. This credits that member, earns you a point and marks your thread as Resolved so everyone will know you have been helped.
I made the assumption when I started this that the data would be sorted by the first column, which may not be true. The hashtable will not allow duplicate keys, so you'll get that error if the same text appears in multiple sections in the table. I swapped
the HashTable out for a List<int> and that covers it.
public class RowCounts : System.Collections.Generic.List<int> { }
protected void GridView1_DataBound(object sender, EventArgs e)
{
// Added reference to the GridView and updated all references
// to use gv instead of GridView1.
GridView gv = (GridView)sender;
string text = "";
int count = 0;
// Changed from HashTable to List (no key, allows duplicates)
RowCounts rowCounts = new RowCounts();
// loop through all rows to get row counts
foreach (GridViewRow gvr in gv.Rows)
{
if (gvr.RowType == DataControlRowType.DataRow)
{
if (gvr.Cells[0].Text == text)
{
count++;
}
else
{
if (count > 0)
{
rowCounts.Add(count);
}
text = gvr.Cells[0].Text;
count = 1;
}
}
}
// Was previously (count > 1), which doesn't cover the last
// row with a unique value
if (count > 0)
{
rowCounts.Add(count);
}
// loop through all rows again to set rowspan
text = "";
string currentColor = "altRowStyle";
int i = 0;
foreach (GridViewRow gvr in gv.Rows)
{
if (gvr.RowType == DataControlRowType.DataRow)
{
if (gvr.Cells[0].Text == text)
{
gvr.Cells.Remove(gvr.Cells[0]);
}
else
{
text = gvr.Cells[0].Text;
// Related to the count update above, check for null
count = (rowCounts[i] != null) ? rowCounts[i++] : 1;
if (count > 1)
gvr.Cells[0].RowSpan = count;
// Start of new row, alternate color
currentColor = GetRowColor(currentColor);
// If not the first row, set a thicker border
if (gvr.RowIndex > 0)
{
gvr.CssClass += String.Concat(" ", "thickBorder");
}
}
// Set background color
gvr.CssClass += String.Concat(" ", currentColor);
}
}
}
Don't forget to click "Mark as Answer" on the post that helped you. This credits that member, earns you a point and marks your thread as Resolved so everyone will know you have been helped.
It worked like a charm. Thank you so much for your help. I'll try on making two grouping. I have a datatable that has Asset Category and sub sectory category.
agolden
Star
7893 Points
1060 Posts
Re: Merge Cell in GridView
Dec 23, 2006 05:24 PM|LINK
I updated the code to set the top border to a thicker border at the start of each section. I also moved the styling into CSS.
<%@ Page Language="C#" %> <%@ Import Namespace="System.Data" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> protected void GridView1_DataBound(object sender, EventArgs e) { string text = ""; int count = 0; Hashtable ht = new Hashtable(); // loop through all rows to get row counts foreach (GridViewRow gvr in GridView1.Rows) { if (gvr.RowType == DataControlRowType.DataRow) { if (gvr.Cells[0].Text == text) { count++; } else { if (count > 0) { ht.Add(text, count); } text = gvr.Cells[0].Text; count = 1; } } } if (count > 1) { ht.Add(text, count); } // loop through all rows again to set rowspan text = ""; string currentColor = "altRowStyle"; foreach (GridViewRow gvr in GridView1.Rows) { if (gvr.RowType == DataControlRowType.DataRow) { if (gvr.Cells[0].Text == text) { gvr.Cells.Remove(gvr.Cells[0]); } else { text = gvr.Cells[0].Text; count = Int32.Parse(ht[text].ToString()); if (count > 1) gvr.Cells[0].RowSpan = count; // Start of new row, alternate color currentColor = GetRowColor(currentColor); // If not the first row, set a thicker border if (gvr.RowIndex > 0) { gvr.CssClass += String.Concat(" ", "thickBorder"); } } // Set background color gvr.CssClass += String.Concat(" ", currentColor); } } } protected string GetRowColor(string originalColor) { return (originalColor == "altRowStyle") ? "rowStyle" : "altRowStyle"; } protected void Page_Load(object sender, EventArgs e) { DataTable dt = new DataTable(); dt.Columns.Add("this"); dt.Columns.Add("is"); dt.Columns.Add("a"); dt.Columns.Add("test"); DataRow dr = dt.NewRow(); dr["this"] = "data1"; dr["is"] = "data1"; dr["a"] = "data1"; dr["test"] = "data1"; dt.Rows.Add(dr); dr = dt.NewRow(); dr["this"] = "data1"; dr["is"] = "data1"; dr["a"] = "data1"; dr["test"] = "data1"; dt.Rows.Add(dr); dr = dt.NewRow(); dr["this"] = "data1"; dr["is"] = "data1"; dr["a"] = "data1"; dr["test"] = "data1"; dt.Rows.Add(dr); dr = dt.NewRow(); dr["this"] = "data2"; dr["is"] = "data2"; dr["a"] = "data2"; dr["test"] = "data2"; dt.Rows.Add(dr); dr = dt.NewRow(); dr["this"] = "data2"; dr["is"] = "data2"; dr["a"] = "data2"; dr["test"] = "data2"; dt.Rows.Add(dr); dr = dt.NewRow(); dr["this"] = "data3"; dr["is"] = "data3"; dr["a"] = "data3"; dr["test"] = "data3"; dt.Rows.Add(dr); dr = dt.NewRow(); dr["this"] = "data4"; dr["is"] = "data4"; dr["a"] = "data4"; dr["test"] = "data4"; dt.Rows.Add(dr); dr = dt.NewRow(); dr["this"] = "data4"; dr["is"] = "data4"; dr["a"] = "data4"; dr["test"] = "data4"; dt.Rows.Add(dr); dr = dt.NewRow(); dr["this"] = "data4"; dr["is"] = "data4"; dr["a"] = "data4"; dr["test"] = "data4"; dt.Rows.Add(dr); GridView1.DataSource = dt; GridView1.DataBind(); } </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Untitled Page</title> <style type="text/css"> table.default { color: #DDD; text-align: center; border: 3px solid #333; } table.default td { border-top: 1px solid #CCC; } table.default th { background-color: #333; } tr.thickBorder td { border-top: 3px solid #333; } tr.rowStyle { background-color: Firebrick; } tr.altRowStyle { background-color: DimGray; } </style> </head> <body> <form id="form1" runat="server"> <div> </div> <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" OnDataBound="GridView1_DataBound" GridLines="None" CssClass="default" Width="300px"> <Columns> <asp:BoundField DataField="This" HeaderText="This" /> <asp:BoundField DataField="Is" HeaderText="Is" /> <asp:BoundField DataField="A" HeaderText="A" /> <asp:BoundField DataField="Test" HeaderText="Test" /> </Columns> </asp:GridView> </form> </body> </html>m_ganish
Member
65 Points
22 Posts
Re: Merge Cell in GridView
Dec 26, 2006 01:44 PM|LINK
Thanks a lot!!!
Will try this example..
Thanks
Ganesh
Webmaster_Vo...
Member
186 Points
86 Posts
Re: Merge Cell in GridView
Dec 26, 2006 04:35 PM|LINK
Hi
I was wondering if you would want to use sqldatasource, how would you do it?
thanks.
agolden
Star
7893 Points
1060 Posts
Re: Merge Cell in GridView
Dec 26, 2006 05:26 PM|LINK
The DataBound method should work for any gridview, whatever data source it's bound to. You'll just need to assign a SqlDataSource to the GridView (and remove the Page_Load parts to create the DataTable and bind it to the grid). I included the DataTable in this example so it could be run as is.
I did find a few bugs that are cleaned up in the version below (with comments on the changes):
protected void GridView1_DataBound(object sender, EventArgs e) { // Added reference to the GridView and updated all references // to use gv instead of GridView1. GridView gv = (GridView)sender; string text = ""; int count = 0; Hashtable ht = new Hashtable(); // loop through all rows to get row counts foreach (GridViewRow gvr in gv.Rows) { if (gvr.RowType == DataControlRowType.DataRow) { if (gvr.Cells[0].Text == text) { count++; } else { if (count > 0) { ht.Add(text, count); } text = gvr.Cells[0].Text; count = 1; } } } // Was previously (count > 1), which doesn't cover the last // row with a unique value if (count > 0) { ht.Add(text, count); } // loop through all rows again to set rowspan text = ""; string currentColor = "altRowStyle"; foreach (GridViewRow gvr in gv.Rows) { if (gvr.RowType == DataControlRowType.DataRow) { if (gvr.Cells[0].Text == text) { gvr.Cells.Remove(gvr.Cells[0]); } else { text = gvr.Cells[0].Text; // Related to the count update above, check for null count = (ht[text] != null) ? Int32.Parse(ht[text].ToString()) : 1; if (count > 1) gvr.Cells[0].RowSpan = count; // Start of new row, alternate color currentColor = GetRowColor(currentColor); // If not the first row, set a thicker border if (gvr.RowIndex > 0) { gvr.CssClass += String.Concat(" ", "thickBorder"); } } // Set background color gvr.CssClass += String.Concat(" ", currentColor); } } }Webmaster_Vo...
Member
186 Points
86 Posts
Re: Merge Cell in GridView
Dec 26, 2006 07:12 PM|LINK
Hi,
I tried your example but ige this error "Item has already been added. Key in dictionary: '454' Key being added: '454'"
the error is generated on this code below.
ht.Add(text, count);
Do you know why?
thanks
agolden
Star
7893 Points
1060 Posts
Re: Merge Cell in GridView
Dec 26, 2006 09:05 PM|LINK
I made the assumption when I started this that the data would be sorted by the first column, which may not be true. The hashtable will not allow duplicate keys, so you'll get that error if the same text appears in multiple sections in the table. I swapped the HashTable out for a List<int> and that covers it.
public class RowCounts : System.Collections.Generic.List<int> { } protected void GridView1_DataBound(object sender, EventArgs e) { // Added reference to the GridView and updated all references // to use gv instead of GridView1. GridView gv = (GridView)sender; string text = ""; int count = 0; // Changed from HashTable to List (no key, allows duplicates) RowCounts rowCounts = new RowCounts(); // loop through all rows to get row counts foreach (GridViewRow gvr in gv.Rows) { if (gvr.RowType == DataControlRowType.DataRow) { if (gvr.Cells[0].Text == text) { count++; } else { if (count > 0) { rowCounts.Add(count); } text = gvr.Cells[0].Text; count = 1; } } } // Was previously (count > 1), which doesn't cover the last // row with a unique value if (count > 0) { rowCounts.Add(count); } // loop through all rows again to set rowspan text = ""; string currentColor = "altRowStyle"; int i = 0; foreach (GridViewRow gvr in gv.Rows) { if (gvr.RowType == DataControlRowType.DataRow) { if (gvr.Cells[0].Text == text) { gvr.Cells.Remove(gvr.Cells[0]); } else { text = gvr.Cells[0].Text; // Related to the count update above, check for null count = (rowCounts[i] != null) ? rowCounts[i++] : 1; if (count > 1) gvr.Cells[0].RowSpan = count; // Start of new row, alternate color currentColor = GetRowColor(currentColor); // If not the first row, set a thicker border if (gvr.RowIndex > 0) { gvr.CssClass += String.Concat(" ", "thickBorder"); } } // Set background color gvr.CssClass += String.Concat(" ", currentColor); } } }Webmaster_Vo...
Member
186 Points
86 Posts
Re: Merge Cell in GridView
Dec 26, 2006 09:34 PM|LINK
Hi agolden,
It worked like a charm. Thank you so much for your help. I'll try on making two grouping. I have a datatable that has Asset Category and sub sectory category.
Thanks.
m_ganish
Member
65 Points
22 Posts
Re: Merge Cell in GridView
Dec 29, 2006 03:27 AM|LINK
Hi,
This is really very nice when compared to previous post.
Thanks a lot!!!
Ganesh
prashant_vic...
Participant
1155 Points
437 Posts
Re: Merge Cell in GridView
Dec 29, 2006 05:03 AM|LINK
Very good example, Really
This helps me a lot in maintaing my grid.
Webmaster_Vo...
Member
186 Points
86 Posts
Re: Merge Cell in GridView
Dec 29, 2006 06:52 PM|LINK