Add Gridview Row AFTER Header - asp.net

i'm trying to add a new headerrow to a Gridview. This row should appear below the original headerrow.
As far as I know I have two events to choose from:
1.) Gridview_RowDataBound
2.) Gridview_RowCreated
Option 1 is not an option as the grid is not binding the data on each postback.
Option 2 does not work as expected. I can add the row, but it is added before the HeaderRow because the HeaderRow itself is not added yet in this event...
Please assist, thank you!
Code: (InnerTable property is exposed by custom gridview)
Private Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
If e.Row.RowType = DataControlRowType.Header Then
Dim r As New GridViewRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal)
For Each c As DataControlField In CType(sender, GridView).Columns
Dim nc As New TableCell
nc.Text = c.AccessibleHeaderText
nc.BackColor = Drawing.Color.Cornsilk
r.Cells.Add(nc)
Next
Dim t As Table = GridView1.InnerTable
t.Controls.Add(r)
End If
End Sub

Since this is a custom GridView, why don't you consider overriding the CreateChildControls method?
I.e (sorry, C#):
protected override void CreateChildControls()
{
base.CreateChildControls();
if (HeaderRow != null)
{
GridViewRow header = CreateRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal);
for (int i = 0; i < Columns.Count; i++)
{
TableCell cell = new TableCell();
cell.Text = Columns[i].AccessibleHeaderText;
cell.ForeColor = System.Drawing.Color.Black;
cell.BackColor = System.Drawing.Color.Cornsilk;
header.Cells.Add(cell);
}
Table table = (Table)Controls[0];
table.Rows.AddAt(1, header);
}
}
UPDATE
As was mentioned by Ropstah, the sniplet above does not work with pagination on. I moved the code to a PrepareControlHierarchy and now it works gracefully with pagination, selection, and sorting.
protected override void PrepareControlHierarchy()
{
if (ShowHeader && HeaderRow != null)
{
GridViewRow header = CreateRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal);
for (int i = 0; i < Columns.Count; i++)
{
TableCell cell = new TableCell();
cell.Text = Columns[i].AccessibleHeaderText;
cell.ForeColor = System.Drawing.Color.Black;
cell.BackColor = System.Drawing.Color.Cornsilk;
header.Cells.Add(cell);
}
Table table = (Table)Controls[0];
table.Rows.AddAt(1, header);
}
//it seems that this call works at the beginning just as well
//but I prefer it here, since base does some style manipulation on existing columns
base.PrepareControlHierarchy();
}

Nice work guys, I used your technique for grouping my AJAX enabled gridview, and I searched for a long, long time. Cheers.
protected override void PrepareControlHierarchy()
{
if (GroupColumns)
{
#region Group Column
Table table = (Table)Controls[0];
string lastValue = string.Empty;
foreach (GridViewRow gvr in this.Rows)
{
string currentValue = gvr.Cells[GroupColumnIndex].Text;
if (lastValue.CompareTo(currentValue) != 0)
{
// there's been a change in value in the sorted column
int rowIndex = table.Rows.GetRowIndex(gvr);
// Add a new sort header row
GridViewRow sortRow = new GridViewRow(rowIndex, rowIndex, DataControlRowType.DataRow, DataControlRowState.Normal);
TableCell sortCell = new TableCell();
TableCell blankCell = new TableCell();
sortCell.ColumnSpan = this.Columns.Count - 1;
sortCell.Text = string.Format("{0}", currentValue);
blankCell.CssClass = "group_header_row";
sortCell.CssClass = "group_header_row";
// Add sortCell to sortRow, and sortRow to gridTable
sortRow.Cells.Add(blankCell);
sortRow.Cells.Add(sortCell);
table.Controls.AddAt(rowIndex, sortRow);
// Update lastValue
lastValue = currentValue;
}
}
#endregion
}
HideColumns();
base.PrepareControlHierarchy();
}

Try this when you add the row to the InnerTable:
t.Controls.AddAt(1, r)
Here's a quick basic test I did, which seems to work OK:
Protected Sub gridview_DataBound(ByVal sender As Object, ByVal e As System.EventArgs) Handles gridview.DataBound
Dim g As GridView = CType(sender, GridView)
Dim r As New GridViewRow(0, -1, DataControlRowType.Header, DataControlRowState.Normal)
Dim th As New TableHeaderCell()
th.ColumnSpan = g.Columns.Count
th.Text = "This is my new header"
r.Cells.Add(th)
Dim t As Table = CType(g.Controls(0), Table)
t.Rows.AddAt(1, r)
End Sub

Related

How do I change my Background.Color to Gray for one row in my GridView

I need to change the Background Color for one row in my GridView. My GridView is defined in my code.behind file:
Dim boundColumn As BoundField = New BoundField With {
.HeaderText = "Color",
.DataField = "Color"
}
GridView1.Columns.Add(boundColumn)
Dim txt1732Column = new TemplateField With {
.ItemTemplate = new TextColumn("myTextBox1732"),
.HeaderText = "17/32"
}
GridView1.Columns.Add(txt1732Column)
Dim txt3564Column = new TemplateField With {
.ItemTemplate = new TextColumn("myTextBox3564"),
.HeaderText = "35/64"
}
GridView1.Columns.Add(txt3564Column)
Dim txt916Column = new TemplateField With {
.ItemTemplate = new TextColumn("myTextBox916"),
.HeaderText = "9/16"
}
GridView1.Columns.Add(txt916Column)
<Snip>...</Snip>
Class TextColumn
Implements ITemplate
Private ReadOnly _myName As String
Public Sub New(myName As String)
_myName = myName
End Sub
Public Sub InstantiateIn(container As Control) Implements ITemplate.InstantiateIn
Dim txt As New TextBox
txt.ID = _myName
txt.Columns = 3
container.Controls.Add(txt)
End Sub
End Class
I need row.index 1 to be gray in background color. I have tried several methods:
For Each row As GridViewRow In GridView1.Rows
If row.RowIndex = 1 Then
row.Style.Add("background-color","gray")
row.BackColor = Color.Gray
row.Cells(1).BackColor = Color.Gray
Dim myTextBox1932 As TextBox = row.Cells(1).FindControl("myTextBox1932")
myTextBox1932.BackColor = Color.Gray
myTextBox1932.Style.Add("background-color","gray")
... with no luck. This GridView displays, but row index 1 is not gray. Thanks in advance.
Try this code
row.DefaultCellStyle.BackColor = Color.Gray
For my situation I moved my code from page_Load to the RowDataBound event handler.
For Each row As GridViewRow In GridView1.Rows
If row.RowIndex = 1 Then
row.BackColor = Color.Gray
End If
Next

how to find control of static control without for loop

private void searchgrid()
{
GridViewRow HeaderGridRow = new GridViewRow(0, 1, DataControlRowType.Header, DataControlRowState.Normal);
TableCell HeaderCell = new TableCell();
HeaderCell.Text = "";
TextBox abc = new TextBox();
HeaderCell.Controls.Add(abc);
HeaderCell.ColumnSpan = 3;
HeaderGridRow.Cells.Add(HeaderCell);
HeaderCell = new TableCell();
HeaderCell.Text = "";
TextBox search = new TextBox();
search.ID = "search1";
HeaderCell.Controls.Add(search);
HeaderCell.ColumnSpan = 3;
HeaderGridRow.Cells.Add(HeaderCell);
HeaderCell = new TableCell();
Button btn_chk = new Button();
btn_chk.Text = "go";
HeaderCell.Controls.Add(btn_chk);
HeaderCell.ColumnSpan = 1;
btn_chk.Click += new EventHandler(btnClick);
HeaderGridRow.Cells.Add(HeaderCell);
//tbl1.Controls.Add(HeaderGridRow);
//btn_chk.CommandName = "btn_chk";
GridView2.Controls[0].Controls.AddAt(0, HeaderGridRow);
//GridView2.Controls[0].Controls.AddAt(0, tbl1);
}
i have a gridview,inside this there is another dynamically created gridview which hAS a textbox.how to find control of this textbox.by looping i get the values but i don get the desired output..so i need just one textbox value..please help
You can do it without a loop like this:
GridView gv = GridView1.Rows[0].FindControl("GridView2") as GridView;
TextBox tb = gv.Rows[0].FindControl("TextBox1") as TextBox;
string tbValue = tb.Text;
You find the nested GridView first and cast it, then you can find the TextBox in the nested GridView.
And you could still always use a loop:
foreach (GridViewRow parentRow in GridView1.Rows)
{
if (parentRow.RowType == DataControlRowType.DataRow)
{
GridView gv = (GridView)parentRow.FindControl("GridView2");
foreach (GridViewRow childRow in gv.Rows)
{
if (childRow.RowType == DataControlRowType.DataRow)
{
TextBox tb = (TextBox)childRow.FindControl("TextBox1");
string tbValue = tb.Text;
}
}
}
}

Add New Rows to GridView

I have a GridView on my page and on a button_OnClick event I'm wanting to add a new row to the grid.
I can add a row to the table using the following code, which works fine, but as I'm binding the DataTable to the grid any previous entries are lost.
string selectedProduct= ddlProducts.SelectedItem.Text;
DataTable dataTable = new DataTable();
dataTable.Columns.Add("Product");
DataRow dataRow;
dataRow = dataTable.NewRow();
dataRow["Product"] = selectedProduct;
dataTable.Rows.Add(dataRow);
grdSelectedProducts.DataSource = dataTable;
grdSelectedProducts.DataBind();
So whilst I understand why this is causing the data loss, I'm not really sure how to get around it.
How can I add a new row to the GridView on each button click whilst retaining the previously added row? The data is not stored anywhere other than the grid itself, so there is no real datasource.
There are options such as Add row to gridview on client side which uses Jquery, but I have read that it isn't a great idea to use that when adding / removing items from the grid. Perhaps that is wrong? Or there is this Add new row to gridview but there isn't much detail there.
You need to store the Products into ViewState (or SessionState or Database) so that it can persist on post back.
For example,
private DataTable ProductDataTable
{
get { return ViewState["ProductDataTable"] as DataTable ?? new DataTable(); }
set { ViewState["ProductDataTable"] = value; }
}
protected void AddRowButton_Click(object sender, EventArgs e)
{
string selectedProduct = ddlProducts.SelectedItem.Text;
// Get the data from ViewState
DataTable dataTable = ProductDataTable;
dataTable.Columns.Add("Product");
DataRow dataRow;
dataRow = dataTable.NewRow();
dataRow["Product"] = selectedProduct;
dataTable.Rows.Add(dataRow);
// Save the data back to ViewState
ProductDataTable = dataTable;
grdSelectedProducts.DataSource = dataTable;
grdSelectedProducts.DataBind();
}
Here is a sample you can try:
DataTable dt = new DataTable(); 
if (ViewState["CurrentTable"]!=null)
{
dt = (DataTable)ViewState["CurrentTable"];
  }
else
{
dt.Columns.Add(new DataColumn("Col1", typeof(string)));
dt.Columns.Add(new DataColumn("Col2", typeof(string)));
}
DataRow dr = null;            
dr = dt.NewRow();
dr["Col1"] = "tes";      
dr["Col2"] = "test";
dt.Rows.Add(dr);
ViewState["CurrentTable"] = dt; 
GridView1.DataSource = dt; 
GridView1.DataBind();
Sorry for bad formatting, typed this with my cellphone. Hope it helps! :-)
// OnButten click
function addrow(sender, args) {
// td add as per your column required
$("#GridView1 tbody").append('<tr><td>00001</td><td>Mr.</td><td>LOKESH N</td></tr>');
}

Add second header row to GridView BELOW already existing header row

I'm trying to dynamically insert a 2nd header row at a GridView's OnRowCreated event. However, I can't seem to get the row to be inserted anywhere besides the first spot in the gridview's row index. The code below fails on the last line, where the header is actually added to the grid. Index out of bounds exception. How can I add this header row below the already existing header row? Help is much appreciated, thanks!
protected void gvwProd_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
GridView gvw = (GridView)sender;
GridViewRow HeaderRow = new GridViewRow(1, 1, DataControlRowType.Header, DataControlRowState.Insert);
TableCell HeaderCell = new TableCell();
HeaderCell.Text = "Prod Comments - TS/LID";
HeaderCell.Style["font-weight"] = "bold";
HeaderCell.ColumnSpan = 4;
HeaderCell.Wrap = false;
HeaderRow.Cells.Add(HeaderCell);
HeaderCell = new TableCell();
HeaderCell.Text = "Materials Comments - TS/LD";
HeaderCell.Style["font-weight"] = "bold";
HeaderCell.ColumnSpan = 8;
HeaderCell.Wrap = false;
HeaderRow.Cells.Add(HeaderCell);
HeaderCell = new TableCell();
HeaderCell.Text = "Plant Comments - TS/LID";
HeaderCell.Style["font-weight"] = "bold";
HeaderCell.ColumnSpan = 11;
HeaderCell.Wrap = false;
HeaderRow.Cells.Add(HeaderCell);
gvw.Controls[0].Controls.AddAt(1, HeaderRow);
}
}
Had a similar problem. You could try casting the GridView to a Table and access the .Rows method:
((Table)gvw.Controls[0]).Rows.AddAt(1, HeaderRow);
source

Error with the event handlers of dynamic linkbutton

I am retrieving data from database depending upon the texboxes input and storing in a datatable , after then from datatable im sending data into dynamic table and displaying table in a panel,in the table all the data of the first column are of linkbuttons, i wrote event handler for dynamic link buttons , but the event handler is not triggering, and i want to store the linkbutton text in a string in the event handler, but the event handler is not triggering.
Code:
protected void Button1_Click(object sender, EventArgs e)
{
// GridView1.
DataTable dt = new DataTable();
OleDbConnection con = new OleDbConnection(str);
con.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = con;
cmd.CommandText = "select ID,title,desc from [SO] where ID='" + TextBox1.Text.ToString() + "'or title='" + TextBox2.Text.ToString() + "'";
OleDbDataAdapter db = new OleDbDataAdapter(cmd);
db.Fill(dt);
Table tb = new Table();
tb.BorderColor = Color.Black;
tb.BorderWidth = 2;
DataRow dr;
for (int i = 0; i < dt.Rows.Count; i++)
{
TableRow tr = new TableRow();
tr.BorderColor = Color.Black;
tr.BorderWidth = 2;
tr.ID = "tr" + i;
TableCell tc = new TableCell();
tc.BorderColor = Color.Black;
tc.BorderWidth = 2;
tc.ID = "tc" + i;
TableCell tc1 = new TableCell();
tc1.BorderColor = Color.Black;
tc1.BorderWidth = 2;
tc1.ID = "tc1" + i;
TableCell tc2 = new TableCell();
tc2.BorderColor = Color.Black;
tc2.BorderWidth = 2;
tc2.ID = "tc2" + i;
LinkButton t = new LinkButton();
t.BorderColor = Color.Black;
t.BorderWidth = 2;
t.ID = "t" + i;
t.Click += new EventHandler(t_edit);
TextBox t1 = new TextBox();
t1.BorderColor = Color.Black;
t1.BorderWidth = 2;
t1.ID = "t1" + i;
TextBox t2 = new TextBox();
t2.BorderColor = Color.Black;
t2.BorderWidth = 2;
t2.ID = "t2" + i;
dr = dt.Rows[i];
t.Text = Convert.ToString(dr["ID"]);
t1.Text = Convert.ToString(dr["title"]);
t2.Text = Convert.ToString(dr["desc"]);
tc.Controls.Add(t);
tc1.Controls.Add(t1);
tc2.Controls.Add(t2);
tr.Cells.Add(tc);
tr.Cells.Add(tc1);
tr.Cells.Add(tc2);
tb.Rows.Add(tr);
}
Panel1.Controls.Add(tb);
}
protected void t_edit(object sender, EventArgs e)
{
}
k but by using the sessions concept im retrieving the total table so that the linkbuttons are also retrieving , and i want to add the linkbttons on a button click , here the problem is the eventhandler is not assiging to the linkbutton, and im adding linkbuttons on button click,not on page load.
You must have to use Page_Init or Page_Load event handler to write code that create controls dynamically. Please read MSDN pages on How to add controls dynamically and ASP.NET Page life cycle articles.
You can add event handlers to the Page_Load event but the important think to remember is that they must be added on every page load. It is common to do setup type tasks such as this in a !Page.IsPostBack clause. When wiring up event handlers that's not the case otherwise they will seem to disappear
if(!Page.PostBack)
{
control.EventRaised += new EventHandler(EventResponse)
}
is wrong and will result in the handler disappearing on postback

Resources