Reputation: 298
I have a GridView with dynamically generated columns based on the user's query. This means that sometimes I can have 1 column with xxx column name, or I can have up to 4 columns.
So: () means optional
AAA | (BBB) | (CCC) | (DDD)
1 7 45 2
22 9 6 33
... ... ... ...
I need to sum up the totals of each of the columns without knowing which columns will be available until the program runs.
I'm trying to use the e.Row.RowType == DataControlRowType.Footer portion of the GridView_RowDataBound event, but I can't seem to figure out how to get it to work.
I am saving the running totals in variables via the e.Row.RowType == DataControlRowType.DataRow portion of the event, but I can't seem to figure out how to "inject" the saved items into the footer of the grid based on the available column(s).
Can anyone give me a bit of assistance?
EDIT
Gridview is done with basic mark up since the columns are built dynamically.
<asp:GridView ID="gv" runat="server" ShowFooter="true" nRowDataBound="gv_RowDataBound">
</asp:GridView>
And then the code for the columns:
private void BindGrid()
{
DataTable dt = new DataTable();
var stt = from t in edcQuery.ToList()
where t.Technician.TeamId == 1
orderby t.RequestType.Name
select new
{
RequestType = t.RequestType.Name,
Tech = t.Technician.Name,
};
dt.Columns.Add("Support Ticket Type");
DataRow dr;
foreach (var col in stt.OrderBy(x => x.Tech).GroupBy(x => x.Tech))
{
dt.Columns.Add(col.Key.Substring(0, col.Key.IndexOf(' ')).Trim());
}
foreach (var type in stt.GroupBy(x => x.RequestType))
{
dr = dt.NewRow();
dr["Support Ticket Type"] = type.Key;
foreach (var tech in type.GroupBy(x => x.Tech))
{
dr[tech.Key.Substring(0, tech.Key.IndexOf(' ')).Trim()] = (object)tech.Count() == System.DBNull.Value ? 0 : tech.Count();
}
dt.Rows.Add(dr);
}
//gvEDCSupportTicketType.FooterRow.Cells[2].Text = "0";
gvEDCSupportTicketType.DataSource = dt;
gvEDCSupportTicketType.DataBind();
}
double atot = 0.0;
double btot = 0.0;
double ctot = 0.0;
double dtot = 0.0;
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
var dataRow = (DataRowView)e.Row.DataItem;
string[] columnNames = { "AAA", "BBB", "CCC", "DDD" };
foreach (var item in columnNames)
{
var checkName = dataRow.Row.Table.Columns.Cast<DataColumn>().Any(x => x.ColumnName.Equals(item, StringComparison.InvariantCultureIgnoreCase));
if (checkName)
{
if (DataBinder.Eval(e.Row.DataItem, item) != DBNull.Value && Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, item)) != 0)
{
switch (item)
{
case "AAA":
atot += Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, item));
break;
case "BBB":
btot += Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, item));
break;
case "CCC":
ctot += Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, item));
break;
case "DDD":
dtot += Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, item));
break;
}
}
}
}
}
else if (e.Row.RowType == DataControlRowType.Footer)
{
e.Row.Cells[0].Text = "Totals:";
e.Row.Cells[0].Attributes.Add("style", "text-align: right;");
}
}
So as you can see, it builds the grid from a datatable and only uses the columns necessary at run time. there is no static FooterTemplate or anything.
Upvotes: 0
Views: 717
Reputation: 1391
I think you should use try catch for this like below.
else if (e.Row.RowType == DataControlRowType.Footer)
{
try
{
e.Row.Cells[0].Text = "Totals:" + atot.ToString();
e.Row.Cells[0].Attributes.Add("style", "text-align: right;");
}
catch
{
}
try
{
e.Row.Cells[1].Text = "Totals:" + btot.ToString();
e.Row.Cells[1].Attributes.Add("style", "text-align: right;");
}
catch
{
}
try
{
e.Row.Cells[2].Text = "Totals:" + ctot.ToString();
e.Row.Cells[2].Attributes.Add("style", "text-align: right;");
}
catch
{
}
try
{
e.Row.Cells[3].Text = "Totals:" + dtot.ToString();
e.Row.Cells[3].Attributes.Add("style", "text-align: right;");
}
catch
{
}
}
OR
else if (e.Row.RowType == DataControlRowType.Footer)
{
int i = 0;
foreach (TableCell c in e.Row.Cells)
{
switch (i)
{
case 0:
c.Text = "Totals:" + atot.ToString();
c.Attributes.Add("style", "text-align: right;");
break;
case 1:
c.Text = "Totals:" + btot.ToString();
c.Attributes.Add("style", "text-align: right;");
break;
case 2:
c.Text = "Totals:" + ctot.ToString();
c.Attributes.Add("style", "text-align: right;");
break;
case 3:
c.Text = "Totals:" + dtot.ToString();
c.Attributes.Add("style", "text-align: right;");
break;
}
i++;
}
}
So if there is footer cell available , it will go through otherwise go to catch part.
Upvotes: 1