I have some data in gridview as below.
I want to merge the rows in gridview as below.
I already tried with below code in RowDataBound() and PreRender(), the result is not the same as I want.
for (int rowIndex = GridView1.Rows.Count - 2; rowIndex >= 0; rowIndex--)
{
GridViewRow gvRow = GridView1.Rows[rowIndex];
GridViewRow gvPreviousRow = GridView1.Rows[rowIndex + 1];
for (int cellCount = 0; cellCount < gvRow.Cells.Count; cellCount++)
{
if (gvRow.Cells[cellCount].Text ==
gvPreviousRow.Cells[cellCount].Text)
{
if (gvPreviousRow.Cells[cellCount].RowSpan < 2)
{
gvRow.Cells[cellCount].RowSpan = 2;
}
else
{
gvRow.Cells[cellCount].RowSpan =
gvPreviousRow.Cells[cellCount].RowSpan + 1;
}
gvPreviousRow.Cells[cellCount].Visible = false;
}
}
}
In aspx,
<asp:GridView ID="GridView1" runat="server" Width="100%"
AutoGenerateColumns = "false" AlternatingRowStyle-BackColor = "#fffccc" HeaderStyle-ForeColor ="#ffffff"
HeaderStyle-BackColor = "#333" AllowPaging ="true" OnRowDataBound="GridView1_RowDataBound" PageSize = "20"
OnPageIndexChanging="GridView1_PageIndexChanging" OnPreRender="GridView1_PreRender">
<HeaderStyle Height="30px" />
<Columns>
<asp:TemplateField HeaderText="Client Company">
<ItemTemplate>
<asp:Label ID="lblClientCompany" runat="server" Text='<%# Eval("ClientCompany")%>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Position">
<ItemTemplate>
<asp:Label ID="lblPosition" runat="server" Text='<%# Eval("Position")%>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Candidate">
<ItemTemplate>
<asp:Label ID="lblCandidate" runat="server" Text='<%# Eval("Candidate")%>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Status">
<ItemTemplate>
asp:Label ID="lblStatus" runat="server" Text='<%# Eval("Status")%>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<AlternatingRowStyle BackColor="#fffccc" />
</asp:GridView>
Please help me becasue I have no idea. Thanks.
You need to try the method in DataBound not RowDataBound
DataBound fires after the GridView control binds to a data source(after all rows bound).
RowDataBound fires for each row, when a data row is bound to data in a GridView control.
ASPX
<asp:GridView ID="GridView1" runat="server" Width="100%"
AutoGenerateColumns = "false" AlternatingRowStyle-BackColor = "#fffccc" HeaderStyle-ForeColor ="#ffffff"
HeaderStyle-BackColor = "#333" AllowPaging ="true" OnDataBound="GridView1_DataBound1" PageSize = "20"
OnPageIndexChanging="GridView1_PageIndexChanging">
<HeaderStyle Height="30px" />
<Columns>
<asp:TemplateField HeaderText="Client Company">
<ItemTemplate>
<asp:Label ID="lblClientCompany" runat="server" Text='<%# Eval("ClientCompany")%>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Position">
<ItemTemplate>
<asp:Label ID="lblPosition" runat="server" Text='<%# Eval("Position")%>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Candidate">
<ItemTemplate>
<asp:Label ID="lblCandidate" runat="server" Text='<%# Eval("Candidate")%>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Status">
<ItemTemplate>
asp:Label ID="lblStatus" runat="server" Text='<%# Eval("Status")%>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<AlternatingRowStyle BackColor="#fffccc" />
</asp:GridView>
Code Behind
protected void GridView1_DataBound1(object sender, System.EventArgs e)
{
for (int rowIndex = GridView1.Rows.Count - 2; rowIndex >= 0; rowIndex--)
{
GridViewRow gvRow = GridView1.Rows[rowIndex];
GridViewRow gvPreviousRow = GridView1.Rows[rowIndex + 1];
for (int cellCount = 0; cellCount < gvRow.Cells.Count; cellCount++)
{
if (gvRow.Cells[cellCount].Text ==
gvPreviousRow.Cells[cellCount].Text)
{
if (gvPreviousRow.Cells[cellCount].RowSpan < 2)
{
gvRow.Cells[cellCount].RowSpan = 2;
}
else
{
gvRow.Cells[cellCount].RowSpan =
gvPreviousRow.Cells[cellCount].RowSpan + 1;
}
gvPreviousRow.Cells[cellCount].Visible = false;
}
}
}
}
As suggested by Vignesh Kumar, the processing can be done in the DataBound event, after all the rows have been populated.
In order to retrieve the fields values, I suggest adding them to the DataKeyNames attribute of the GridView:
<asp:GridView ID="GridView1" runat="server" DataKeyNames="ClientCompany,Position" OnDataBound="GridView1_DataBound" ... />
Here is the code to combine the cells:
protected void GridView1_DataBound(object sender, EventArgs e)
{
for (int currentRowIndex = 0; currentRowIndex < GridView1.Rows.Count; currentRowIndex++)
{
GridViewRow currentRow = GridView1.Rows[currentRowIndex];
CombineColumnCells(currentRow, 0, "ClientCompany");
CombineColumnCells(currentRow, 1, "Position");
}
}
private void CombineColumnCells(GridViewRow currentRow, int colIndex, string fieldName)
{
TableCell currentCell = currentRow.Cells[colIndex];
if (currentCell.Visible)
{
Object currentValue = GridView1.DataKeys[currentRow.RowIndex].Values[fieldName];
for (int nextRowIndex = currentRow.RowIndex + 1; nextRowIndex < GridView1.Rows.Count; nextRowIndex++)
{
Object nextValue = GridView1.DataKeys[nextRowIndex].Values[fieldName];
if (nextValue.ToString() == currentValue.ToString())
{
GridViewRow nextRow = GridView1.Rows[nextRowIndex];
TableCell nextCell = nextRow.Cells[colIndex];
currentCell.RowSpan = Math.Max(1, currentCell.RowSpan) + 1;
nextCell.Visible = false;
}
else
{
break;
}
}
}
}
I have created for first column in vb.net code behind:
Note: Column should be BoundField.
<asp:BoundField DataField="ProductID" HeaderText="ProductID">
<ItemStyle Width="70px" HorizontalAlign="Center" />
</asp:BoundField>
VB.Net code behind:
Private Sub gvGridView_DataBound(sender As Object, e As EventArgs) Handles gvGridView.DataBound
Dim rowCount As Integer = gvTranscript1.Rows.Count
Dim RowIndex As Integer = 0
Dim gvRow As GridViewRow
Dim gvPrevRow As GridViewRow
Dim cellIndex As Integer = 0
For RowIndex = rowCount - 2 To 0 Step -1
gvRow = gvTranscript1.Rows(RowIndex) 'second last
gvPrevRow = gvTranscript1.Rows(RowIndex + 1) 'last
'lblmsg.Text += gvRow.Cells(0).Text & " - " & gvPrevRow.Cells(0).Text & "<br>"
If gvRow.Cells(0).Text = gvPrevRow.Cells(0).Text Then
If gvPrevRow.Cells(cellIndex).RowSpan < 2 Then
gvRow.Cells(cellIndex).RowSpan = 2
Else
gvRow.Cells(cellIndex).RowSpan = gvPrevRow.Cells(cellIndex).RowSpan + 1
End If
gvPrevRow.Cells(0).Visible = False
End If
Next
End Sub
Dim rows = GridView1.Rows.Cast(Of GridViewRow).Union(GridView2.Rows.Cast(Of GridViewRow)).ToArray().Select(Function(f) New With {.YourColumn1 = f.Cells(0).Text, .YourColumn2 = f.Cells(1).Text, .YourColumnN = f.Cells(n).Text})
GridView1.DataSource = rows
GridView1.DataBind()
Remove ItemTemplate and take boundField Columns
Related
I need to change the gridview cell color to red if the value is <=0. I have tried the below piece of code and it doesn't take the cell value of each row.
How can I get each cell value of gridview.
Code:
if (e.Row.RowType == DataControlRowType.DataRow)
{
foreach (GridViewRow row in GridView1.Rows)
{
for (int i = 0; i < GridView1.Columns.Count; i++)
{
TableCell cell = row.Cells[i];
int quantity = int.Parse(cell.Text);
if (quantity <= 0)
{
cell.ForeColor = Color.Red;
}
}
}
}
If you want to change the foreground color or access the text, you should use itemtemplate instead of boundField.
<asp:TemplateField HeaderText="Status" ControlStyle-Width="75px" >
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Eval("ParentID") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
and you can bind this variable like
protected void GridView1_DataBound(object sender, EventArgs e)
{
for (int i =0 ; i <= GridView1.Rows.Count -1 ;i++)
{
Label lblparent = (Label)GridView1.Rows[i].FindControl("Label1");
if (lblparent.Text == "1")
{
GridView1.Rows[i].Cells[6].BackColor = Color.Yellow;
lblparent.ForeColor = Color.Black;
}
else
{
GridView1.Rows[i].Cells[6].BackColor = Color.Green;
lblparent.ForeColor = Color.Yellow;
}
}
}
for more help check this
https://forums.asp.net/t/1747819.aspx?how+to+change+gridview+cell+color+based+on+cell+item
Your code worked for me. I put it into DataBound event:
protected void GridView1_DataBound(object sender, EventArgs e)
{
foreach (GridViewRow row in GridView1.Rows)
{
for (int i = 0; i < GridView1.Columns.Count; i++)
{
TableCell cell = row.Cells[i];
int quantity = int.Parse(cell.Text);
if (quantity <= 0)
{
cell.ForeColor = System.Drawing.Color.Red;
}
}
}
}
My gridview code is:
<asp:GridView ID="GridView1" HeaderStyle-BackColor="#3AC0F2" HeaderStyle-ForeColor="White" runat="server" AutoGenerateColumns="false" OnDataBound="GridView1_DataBound">
<Columns>
<asp:BoundField DataField="ID" HeaderText="ID" ItemStyle-Width="30" />
<asp:BoundField DataField="quantity" HeaderText="Quantity" ItemStyle-Width="150" />
<asp:BoundField DataField="number" HeaderText="number" ItemStyle-Width="150" />
</Columns>
</asp:GridView>
I think the key is OnDataBound="GridView1_DataBound" on your GridView1
This is the code you are looking for :
Label lblInfo = (Label)gvVisa_Mofa.Rows[i].FindControl("lblInfo");
if (lblInfo.Text <= "0")
{
gvVisa_Mofa.Rows[i].BackColor = System.Drawing.ColorTranslator.FromHtml("#EDA3A3");
}
another method :
if (e.Row.RowType == DataControlRowType.DataRow)
{
If(Condition True)
{
e.Row.BackColor = Drawing.Color.Red
}
}
I have a asp:gridview that has CSS and a OnRowDataBound event. If I remove my OnRowDataBound event, the CSS functions just as I want, but if I leave the CSS and OnRowDataBound event then the CSS never fires.
Can someone help me with what will have both of these methods fire and function at the same time?
ASP/HTML
<asp:GridView ID="gvEmps" runat="server" CssClass="Grid" OnRowDataBound="gvEmps_OnRowDataBound" >
<Columns>
<asp:BoundField DataField="EmpName" HeaderText="Name"> <ItemStyle CssClass="cellOneCellPadding" Width="50%" /></asp:BoundField>
<asp:BoundField DataField="EmpAddress" HeaderText="Address"> <ItemStyle HorizontalAlign="Center"/></asp:BoundField>
<asp:BoundField DataField="EmpCity" HeaderText="City"> <ItemStyle HorizontalAlign="Center"/></asp:BoundField>
<asp:BoundField DataField="EmpState" HeaderText="State"> <ItemStyle HorizontalAlign="Center"/></asp:BoundField>
<asp:BoundField DataField="EmpZip" HeaderText="Zip"> <ItemStyle HorizontalAlign="Center"/></asp:BoundField>
<asp:BoundField DataField="EmpPhone" HeaderText="Phone"> <ItemStyle HorizontalAlign="Center"/></asp:BoundField>
</Columns>
</asp:GridView>
C# Method gvEmps_OnRowDataBound....
if (e.Row.RowType == DataControlRowType.DataRow)
{
foreach (TableCell row in e.Row.Cells)
{
if (design1.Any(x => x == e.Row.Cells[0].Text.ToUpper())) { row.CssClass = "des1"; }
else if (design2.Any(x => x == e.Row.Cells[0].Text)) { row.CssClass = "des2"; }
else if (design3.Any(x => x == e.Row.Cells[0].Text)) { row.CssClass = "des3"; }
else { row.CssClass = "defaultview"; };
}
}
CSS
.cellOneCellPadding {
padding-left: 9pt !important;
}
You're reassigning the CssClass property in your OnRowDataBound function and overwriting the CssClass initially provided in your template. Change up your foreach to look like this:
foreach (TableCell row in e.Row.Cells)
{
if (design1.Any(x => x == e.Row.Cells[0].Text.ToUpper())) { row.CssClass += " des1"; }
else if (design2.Any(x => x == e.Row.Cells[0].Text)) { row.CssClass += " des2"; }
else if (design3.Any(x => x == e.Row.Cells[0].Text)) { row.CssClass += " des3"; }
else { row.CssClass += " defaultview"; };
}
I am trying to change the an expiration date column on a gridview. I want to change color when I am past the current date or within 15 days of current date change color to red and if 15 to 30 days from current data date set color to yellow. When I try to implement the rowdatabound while trying to set datetime variable I am missing rows from gridview and colors are not shown.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" AllowSorting="True" OnDataBound="GridView1_DataBound" OnRowDataBound="GridView1_RowDataBound1">
<Columns>
<asp:BoundField DataField="MLSId" HeaderText="MLSId" SortExpression="MLSId" />
<asp:BoundField DataField="Agent_FName" HeaderText="First Name" SortExpression="Agent_FName" />
<asp:BoundField DataField="Agent_LName" HeaderText="Last Name" SortExpression="Agent_LName" />
<asp:BoundField DataField="License_Num" HeaderText="License #" SortExpression="License_Num" />
<asp:TemplateField HeaderText="License Exp" SortExpression="License_Exp">
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("License_Exp") %>'></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("License_Exp", "{0:MM/dd/yyyy}") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code Behind,
protected void GridView1_RowDataBound1(object sender, GridViewRowEventArgs e)
{
for (int i = 0; i <= GridView1.Rows.Count-1; i++)
{
DateTime lblDate = Convert.ToDateTime(GridView1.Rows[i].FindControl("Label1"));
if (lblDate <= DateTime.Now.AddDays(15))
{
GridView1.Rows[i].Cells[4].BackColor = Color.Red;
}
else if (lblDate >= DateTime.Now.AddDays(16) && lblDate <= DateTime.Now.AddDays(30))
{
GridView1.Rows[i].Cells[4].BackColor = Color.Yellow;
}
else
{
GridView1.Rows[i].Cells[4].BackColor = Color.Blue;
}
}
}
You don't need for block inside GridView1_RowDataBound1, here's what you should do instead:
protected void GridView1_RowDataBound1(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
string dateText = ((Label)e.Row.FindControl("Label1")).Text;
if (!string.IsNullOrEmpty(dateText))
{
DateTime dateValue = DateTime.ParseExact(dateText, "MM/dd/yyyy", null);
if (dateValue <= DateTime.Now.AddDays(15))
{
e.Row.Cells[4].BackColor = Color.Red;
}
else if (dateValue >= DateTime.Now.AddDays(16) && dateValue <= DateTime.Now.AddDays(30))
{
e.Row.Cells[4].BackColor = Color.Yellow;
}
else
{
e.Row.Cells[4].BackColor = Color.Blue;
}
}
else
{
e.Row.Cells[4].BackColor = Color.Blue;
}
}
}
RowDataBound event is raised for each row and you can get the row using e.Row
You can change the code as below. make sure you have find the label and convert it to date time without any errors.
protected void GridView1_RowDataBound1(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Label a = e.Row.FindControl("Label1") as Label;
if (a != null)
{
DateTime lblDate;
if(!DateTime.TryParse(a.Text, out lblDate)
{
// date time conversion not success
// you may have empty or invalid datetime
// do something in this case
return;
}
if (lblDate <= DateTime.Now.AddDays(15))
{
e.Row.Cells[4].BackColor = Color.Red;
}
else if (lblDate >= DateTime.Now.AddDays(16) && lblDate <= DateTime.Now.AddDays(30))
{
e.Row.Cells[4].BackColor = Color.Yellow;
}
else
{
e.Row.Cells[4].BackColor = Color.Blue;
}
}
}
}
I have three GridView that for some reason has first duplicate data for the first three column> its not an error because thats how i want it to be.
I want the grid to leave blank where duplicate in the above two columns Client Name and Branch . I loop through my cells and set them to empty on Databound as below.
protected void gvList_RowDataBound(object sender, GridViewRowEventArgs e)
{
string oldValue = string.Empty;
string newValue = string.Empty;
// for (int count = 0; count < gvList.Rows.Count; count++)
for (int j = 0; j < 2; j++)
{
for (int count = 0; count < gvList.Rows.Count; count++)
{
oldValue = gvList.Rows[count].Cells[j].Text;
if (oldValue == newValue)
{
gvList.Rows[count].Cells[j].Text = string.Empty;
}
newValue = oldValue;
}
}
}
After running i get the result below. The grid do what i want to for a row and omit teh row proceeding it. I am confused. Please better alternative would be appreciated.
My second question is , i have another grid also that duplicate few rows. I applied the same method and Dispose() where duplicate but nothing change. I use
gridview.rows[].cells.clear/disposed()`
My girdview is as below.
<asp:GridView ID="gvList" runat="server" AutoGenerateColumns="False" AllowPaging="true" AllowSorting="true" OnSorting="gvList_sorting"
DataKeyNames="contactID" OnPageIndexChanging="gvList_PageIndexChanging" OnRowCancelingEdit="gvList_RowCancelingEdit"
OnRowDeleting="gvList_RowDeleting" OnRowEditing="gvList_RowEditing" OnRowUpdating="gvList_RowUpdating" OnRowDataBound="gvList_RowDataBound"
EnableModelValidation="True" CellPadding="4" ForeColor="#333333" GridLines="None" ShowFooter="True">
<Columns>
<asp:BoundField DataField="cname" HeaderText="Client Name" ReadOnly="true" SortExpression="cname" />
<asp:BoundField DataField="bname" HeaderText="Branch" ReadOnly="true" SortExpression="bname" />
<asp:BoundField DataField="name" HeaderText="Contact " SortExpression="name" />
<asp:BoundField DataField="type" HeaderText="Type " SortExpression="type" ReadOnly="true" />
<asp:BoundField DataField="description" HeaderText="Description " SortExpression="description" ReadOnly="true" />
<asp:CommandField ShowEditButton="true" />
<asp:TemplateField>
<ItemTemplate>
<asp:linkbutton id="ContactlnkDelete" runat="server" text="Delete" causesvalidation="false" commandname="Delete" commandargument="ID">
</asp:linkbutton>
<cc1:modalpopupextender id="lnkDelete_ModalPopupExtender2" runat="server" cancelcontrolid="ButtonDeleteCancel" okcontrolid="ButtonDeleleOkay"
targetcontrolid="ContactlnkDelete" popupcontrolid="DivDeleteConfirmation" backgroundcssclass="ModalPopupBG">
</cc1:modalpopupextender>
<cc1:confirmbuttonextender id="lnkDelete_ConfirmButtonExtender2" runat="server" targetcontrolid="ContactlnkDelete" enabled="True"
displaymodalpopupid="lnkDelete_ModalPopupExtender2">
</cc1:confirmbuttonextender>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
<RowStyle BackColor="#EFF3FB" />
<EditRowStyle BackColor="#2461BF" />
<SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
<PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
<HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
<AlternatingRowStyle BackColor="White" />
</asp:GridView>
but it also failed. Please, i need your assistance.
You must use DataBound instead of RowDataBound like following:
protected void gvList_DataBound(object sender, EventArgs e)
{
string oldValue = string.Empty;
string newValue = string.Empty;
for (int j = 0; j < 2; j++)
{
for (int count = 0; count < gvList.Rows.Count; count++)
{
oldValue = gvList.Rows[count].Cells[j].Text;
if (oldValue == newValue)
{
gvList.Rows[count].Cells[j].Text = string.Empty;
}
newValue = oldValue;
}
}
}
Update:
if you want delete rows:
Replace:
gvList.Rows[count].Cells[j].Text = string.Empty;
with:
gvList.Rows[count].Visible = false;
You are assigning the same value to newValue and OldValue, and "must use Page_Load event insead of RowDataBound" (Thanks to Fer for pointing out what I missed.)
Try this:
for (int column = 0; column < 2; column++)
{
for (int row = 0; row < gvList.Rows.Count; row++)
{
if(gvList.Rows[row].Cells[column].Text != "")
oldValue = gvList.Rows[row].Cells[column].Text;
if (oldValue == newValue)
{
gvList.Rows[row].Cells[column].Text = string.Empty;
}
if(row+1 < gvList.Rows.Count)
newValue = gvList.Rows[row+1].Cells[column].Text;
}
}
In the code above I used a 'for' cycle where the line in position 'i' compares with all the lines in 'j' position, and if there is a match the line in position 'i' is eliminated in order to avoid duplicate data
void delete_Duplicate_data()
{
for (int i = 0; i < Gv.RowCount; i++)
{
for (int j = i + 1; j < Gv.RowCount; j++)
{
if (Gv.Rows[i].Cells[gID.Name].Value.ToString() == Gv.Rows[j].Cells[gID.Name].Value.ToString())
{
Gv.Rows.Remove(Gv.Rows[i]);
}
}
}
}
I need to add multiple footer rows to my RadGrid instance ; for the moment, however, I just want to add second one. I have currently a single footer row and it's working and displaying perfectly, for the record.
I found the following relevant question on the Telerik forums and tried implemeting it but it's not working : the code gets executed, and the new FooterItem gets added to the Controls but that second row just doesn't appear. I need to find out why and I'd be grateful if anyone could help me fix that problem.
ASP grid code
<div id="OrderMainContent">
<telerik:RadAjaxManager runat="server" ID="RadAjaxManager1">
<AjaxSettings>
<telerik:AjaxSetting AjaxControlID="RadGrid1" />
<telerik:AjaxSetting AjaxControlID="txtQuantity">
<UpdatedControls>
<telerik:AjaxUpdatedControl ControlID="RadGrid1" />
</UpdatedControls>
</telerik:AjaxSetting>
</AjaxSettings>
</telerik:RadAjaxManager>
<telerik:RadInputManager ID="RadInputManager1" runat="server">
<telerik:NumericTextBoxSetting BehaviorID="NumericBehavior1" Type="Number" DecimalDigits="0">
<TargetControls>
<telerik:TargetInput ControlID="RadGrid1" />
</TargetControls>
</telerik:NumericTextBoxSetting>
</telerik:RadInputManager>
<telerik:RadGrid ID="RadGrid1" runat="server" Skin="Sunset" AllowSorting="True" AutoGenerateColumns="False"
GridLines="None" ShowFooter="True" OnItemDataBound="RadGrid1_ItemDataBound" OnPreRender="RadGrid1_PreRender">
<MasterTableView DataKeyNames="ProductID" TableLayout="Fixed">
<RowIndicatorColumn>
<HeaderStyle Width="20px"></HeaderStyle>
</RowIndicatorColumn>
<ExpandCollapseColumn>
<HeaderStyle Width="20px"></HeaderStyle>
</ExpandCollapseColumn>
<Columns>
<telerik:GridBoundColumn UniqueName="colProduct" HeaderText="<%$ Resources: SiteLabels, ProductOrderForm.lblProduct %>"
HeaderStyle-HorizontalAlign="Center" DataField="ProdDesc">
<HeaderStyle HorizontalAlign="Center"></HeaderStyle>
</telerik:GridBoundColumn>
<telerik:GridTemplateColumn UniqueName="colQuantity" HeaderText="<%$ Resources: SiteLabels, ProductOrderForm.lblQuantity %>"
HeaderStyle-HorizontalAlign="Center" DataField="OrderQty" ColumnEditorID="txtQuantity">
<HeaderStyle Width="90" />
<ItemStyle Width="90px" />
<ItemTemplate>
<asp:TextBox ID="txtQuantity" runat="server" Width="50px" OnTextChanged="txtQuantity_TextChanged"
AutoPostBack="true">
</asp:TextBox>
</ItemTemplate>
</telerik:GridTemplateColumn>
<telerik:GridTemplateColumn UniqueName="colPrice" HeaderText="<%$ Resources: SiteLabels, ProductOrderForm.lblBasePrice %>"
HeaderStyle-HorizontalAlign="Center" DataField="ProdUnitPrice">
<HeaderStyle Width="80px" />
<ItemStyle Width="80px" />
<ItemTemplate>
<asp:Label ID="lblPrice" runat="server" Text='<%# Eval("ProdUnitPrice") %>' />
</ItemTemplate>
</telerik:GridTemplateColumn>
<telerik:GridBoundColumn UniqueName="colNotes" HeaderText="<%$ Resources: SiteLabels, ProductOrderForm.lblNotes %>"
HeaderStyle-HorizontalAlign="Center">
<HeaderStyle Width="200px" />
<ItemStyle Width="200px" />
</telerik:GridBoundColumn>
</Columns>
</MasterTableView>
<ClientSettings>
<Scrolling AllowScroll="True" UseStaticHeaders="True" />
</ClientSettings>
</telerik:RadGrid>
</div>
Relevant code behind
protected void RadGrid1_PreRender(object sender, EventArgs e)
{
AddFooterRow(sender as RadGrid);
}
private void AddFooterRow(RadGrid grid)
{
if (grid != null)
{
GridItem[] footerItems = grid.MasterTableView.GetItems(GridItemType.Footer);
if (footerItems.Count() == 1)
{
GridTFoot foot = footerItems[0].Parent.Controls[0].Parent as GridTFoot;
for (int i = 0; i < foot.Controls.Count; i++)
{
GridFooterItem item = foot.Controls[i] as GridFooterItem;
if(item != null)
{
lastFooterPos = i;
break;
}
}
GridFooterItem existingFooter = foot.Controls[lastFooterPos] as GridFooterItem;
GridFooterItem newFooterItem = new GridFooterItem(grid.MasterTableView, 0, 0);
foreach(TableCell fc in existingFooter.Cells)
{
TableCell newFooterCell = new TableCell();
newFooterCell.Text = "allo";
newFooterItem.Cells.Add(newFooterCell);
}
foot.Controls.AddAt(lastFooterPos + 1, newFooterItem);
}
}
}
Of course if you need more precisions, just ask. Thank you for your help.
After doing some searching on the Telerik docs, I'm fairly sure this is not just possible. In this question, for instance, a Telerik admin states clearly that "RadGrid is data-bound control and its items are created based on the records in its datasource and display the datasource data. Therefore in order to add new row in the grid, you need to add new record in its datasource and rebind the grid."
So, to work around my problem, I've decided to remove the footer on my grid and add a brand-new grid underneath, which I'll bind to a dummy DataTable I'll create by code in my Page_Load event handler. The values will be either determined client-side through Javascript or simply injected into the rows of that dummy table.
If anyone ever finds a more elegant solution, I'm still interested to know about it! Right now, though, work has to go forward.
int lastFooterPos;
protected void RadGrid1_PreRender(object sender, EventArgs e) {
AddFooterRow(sender as RadGrid);
}
private void AddFooterRow(RadGrid grid) {
if (grid != null) {
GridItem[] footerItems = grid.MasterTableView.GetItems(GridItemType.Footer);
if (footerItems.Length == 1) {
GridTFoot foot = footerItems[0].Parent.Controls[0].Parent as GridTFoot;
for (int i = 0; i < foot.Controls.Count; i++) {
GridFooterItem item = foot.Controls[i] as GridFooterItem;
if (item != null) {
lastFooterPos = i;
break;
}
}
GridFooterItem existingFooter = foot.Controls[lastFooterPos] as GridFooterItem;
GridFooterItem newFooterItem = new GridFooterItem(grid.MasterTableView, 0, 0);
int k = 0;
int l = 0;
int n = 0;
int p = 0;
int a = 0;
int b = 0;
int c = 0;
foreach (TableCell fc in existingFooter.Cells) {
//decimal cost = Convert.ToDecimal(existingFooter["Marks"].Text);
TableCell newFooterCell = new TableCell();
if (k == 0) {
newFooterCell.Text = "";
newFooterCell.Height = 12;
newFooterItem.Cells.Add(newFooterCell);
k = 1;
}
else {
if (l == 0) {
newFooterCell.Text = "";
newFooterCell.Height = 12;
newFooterItem.Cells.Add(newFooterCell);
l = 1;
}
else {
if (n == 0) {
newFooterCell.Text = "";
newFooterCell.Height = 12;
newFooterItem.Cells.Add(newFooterCell);
n = 1;
}
else {
if (p == 0) {
newFooterCell.Text = "Another Total Footer:";
newFooterCell.Height = 12;
newFooterItem.Cells.Add(newFooterCell);
p = 1;
}
else {
if (a == 0) {
newFooterCell.Text = Convert.ToString(existingFooter["Marks"].Text);
newFooterCell.Height = 12;
newFooterItem.Cells.Add(newFooterCell);
a = 1;
}
else {
if (b == 0) {
newFooterCell.Text = Convert.ToString(existingFooter["Fees"].Text);
newFooterCell.Height = 12;
newFooterItem.Cells.Add(newFooterCell);
b = 1;
}
else {
if (c == 0) {
newFooterCell.Text = Convert.ToString(existingFooter["Noofstudents"].Text);
newFooterCell.Height = 12;
newFooterItem.Cells.Add(newFooterCell);
c = 1;
}
else {
newFooterCell.Text = "";
newFooterCell.Height = 12;
newFooterItem.Cells.Add(newFooterCell);
}
}
}
}
}
}
}
foot.Controls.AddAt(lastFooterPos + 1, newFooterItem);
}
}
}
}