find a control by id from Dynamically added Template field in GridView - asp.net

Hi i added template field dynamically to gridview by implementing ITemplate interface.
The template field contains some controls like label and textboxes. how do i get these controls in row databound event.
I am not able to get when i do gridviewrow.findcontrol("id") as i do normally when we add templatefield from aspx page.
The way i added template field is like this
public class CustomGridViewColumn : ITemplate
{
ListItemType _liType;
string _columnName;
public CustomGridViewColumn(ListItemType type, string column)
{
_liType = type;
_columnName = column;
}
void ITemplate.InstantiateIn(System.Web.UI.Control container)
{
switch (_liType)
{
case ListItemType.Header:
Label lblHeader = new Label();
lblHeader.Text = _columnName;
container.Controls.Add(lblHeader);
break;
case ListItemType.Item:
Label lblItem = new Label();
lblItem.DataBinding += new EventHandler(lbl_DataBinding);
lblItem.ID = "lbl" + _columnName;
lblItem.ClientIDMode = ClientIDMode.Predictable;
container.Controls.Add(lblItem);
DropDownList ddl = new DropDownList();
ddl.DataBinding += new EventHandler(ddl_DataBinding);
ddl.ID = "ddl" + _columnName;
ddl.Visible = false;
container.Controls.Add(ddl);
break;
}
}
}
Now i want access the label and dropdown which i have added using this code.
when i do gridviewrow.findcontrol("id") i am not getting them.
Can any one please help me.
I am geeting when i go through all the rows and try to find but
i have a check box in a row when i select it all labels should diappear and ddls dhould appear
for this i am using the follwoing code.
protected void chkEdit_CheckedChanged(object sender, EventArgs e)
{
CheckBox chkEditTest = (CheckBox)sender;
GridViewRow grow = (GridViewRow)chkEditTest.NamingContainer;
DropDownList ddl = (DropDownList)grow.FindControl("ddl");
Label lbl= (Label)grow.FindControl("lbl");
}
when i do this i am not able to get the controls.
it seems like controls are disapppearing on postback..

This is what I came up with and I can able to get the control reference in the code behind.
public class CustomGridViewColumn : ITemplate
{
ListItemType _liType; string _columnName;
public CustomGridViewColumn(ListItemType type, string column)
{
_liType = type;
_columnName = column;
}
void ITemplate.InstantiateIn(Control container)
{
switch (_liType)
{
case ListItemType.Header:
Label lblHeader = new Label();
lblHeader.Text = _columnName;
container.Controls.Add(lblHeader);
break;
case ListItemType.Item:
Label lblItem = new Label();
lblItem.DataBinding += new EventHandler(lblItem_DataBinding);
lblItem.ID = "lbl" + _columnName;
lblItem.ClientIDMode = ClientIDMode.Predictable;
container.Controls.Add(lblItem);
DropDownList ddl = new DropDownList();
ddl.DataBinding += new EventHandler(ddl_DataBinding);
ddl.ID = "ddl" + _columnName;
ddl.Visible = false;
ddl.DataSource = new string[] { "Hello", "World" };
container.Controls.Add(ddl);
break;
}
}
void ddl_DataBinding(object sender, EventArgs e)
{
}
void lblItem_DataBinding(object sender, EventArgs e)
{
}
}
protected void Page_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt.Columns.Add("Name");
DataRow oItem = dt.NewRow();
oItem[0] = "Deepu";
dt.Rows.Add(oItem);
oItem = dt.NewRow();
oItem[0] = "MI";
dt.Rows.Add(oItem);
GridView gv = new GridView();
gv.ID = "myGridView";
gv.AutoGenerateColumns = false;
BoundField nameColumn = new BoundField();
nameColumn.DataField = "Name";
nameColumn.HeaderText = "Name";
gv.Columns.Add(nameColumn);
TemplateField TmpCol = new TemplateField();
TmpCol.HeaderText = "Template Column";
gv.Columns.Add(TmpCol);
TmpCol.ItemTemplate = new CustomGridViewColumn(ListItemType.Item, "TEST");
gv.DataSource = dt;
gv.DataBind();
Form.Controls.Add(gv);
}
protected void Button1_Click(object sender, EventArgs e)
{
GridView gv = Form.FindControl("myGridView") as GridView;
foreach (GridViewRow item in gv.Rows)
{
var ddl = item.FindControl("ddlTest") as DropDownList;
if (ddl != null)
{
ddl.Visible = true;
}
var lbl = item.FindControl("lbl") as Label;
if (lbl != null)
{
lbl.Text = "hello";
}
}
}
<form id="form1" runat="server">
<asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />
</form>
Thanks
Deepu

Can you try using row index of GRIDVIEW control
var rowIndex = int.Parse(e.CommandArgument)
GridView1.Rows[rowIndex].FindControl("id")
Also refer
http://forums.asp.net/t/998368.aspx/1
http://www.codeproject.com/Articles/12021/Accessing-the-different-controls-inside-a-GridView
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridviewrow.aspx
Thanks
Deepu

Related

How to add TemplateField to a gridview in the code behind?

I have a DropDownList which has a list of tables. Under it there is GridView. Based on the table selected from the drop down list box, I will populate the GridView dynamically. Since the tables could have different column names, I need to create the template field for the GridView dynamically.
Following is my bind method. I have two problems:
I couldn’t wrap the binding part in if (!IsPostBack) since the GridView is populated based on the selection of the DropDownList, so everytime I change the selection, the columns will be duplicated.
And I don’t have any data, I think I need to set ItemTemplate of the tField (TemplateField), but how do I do that?
My bind method
private void BindGridView()
{
DataSet ds = new DataSet();
try
{
ds = …
if (ds.Tables.Count > 0)
{
foreach (DataColumn dc in ds.Tables[0].Columns)
{
TemplateField tField = new TemplateField();
tField.HeaderText = dc.ColumnName;
GridView2.Columns.Add(tField);
}
GridView2.DataSource = ds.Tables[0];
GridView2.DataBind();
}
else
{
…
}
}
catch (Exception ex)
{
…
}
}
There are various steps that should be taken care of:
STEP I::
Create a class inheriting the ITemplate interface. Override the method InstantiateIn() of the ITemplate interface.
STEP II:
Define a constructor for your class that takes a ListItemType object as its parameter.
STEP III::
If the Control being added to the container's ControlCollection has to be bound to some DataSource Column, then register the
handler for the OnDataBinding event. When the event occurs, retrieve the text from the data source and assign it to your control. For Example, hyprLnk_DataBinding event is defined for Binding Data to your controls created inside ItemTemplate.
public class TemplateGenerator : ITemplate // Class inheriting ITemplate
{
ListItemType type;
string columnName;
public TemplateGenerator(ListItemType t, string cN)
{
type = t;
columnName= cN;
}
// Override InstantiateIn() method
void ITemplate.InstantiateIn(System.Web.UI.Control container)
{
switch (type)
{
case ListItemType.Item:
HyperLink hyprLnk = new HyperLink();
hyprLnk.Target = "_blank"; //Optional.
hyprLnk.DataBinding+=new EventHandler(hyprLnk_DataBinding);
container.Controls.Add(hyprLnk);
break;
}
}
// The DataBinding event of your controls
void hyprLnk_DataBinding(object sender, EventArgs e)
{
HyperLink hyprlnk = (HyperLink)sender;
GridViewRow container = (GridViewRow)hyprlnk.NamingContainer;
object bindValue = DataBinder.Eval(container.DataItem,columnName);
// Adding check in case Column allows null values
if (bindValue != DBNull.Value)
{
hyprlnk.Text = bindValue.ToString();
hyprlnk.NavigateUrl = "http://www.google.com";
}
}
}
That's all. Above was just a sample to create ItemTemplate dynamically for GridView and add controls to the Item Template.
Now, Below is the function that will actually carry out the calls to create Template Columns dynamically. You can call this function when required for e.g. from your DropDownList event Handler.
protected void GenerateGridViewColumnsDynamically()
{
// Create the TemplateField
TemplateField firstName = new TemplateField();
firstName.HeaderText = "First_Name";
firstName.ItemTemplate = new TemplateGenerator(ListItemType.Item, "FirstName");
// Showing boundField example just for more context
BoundField lastName = new BoundField();
lastName.DataField = "LastName";
lastName.HeaderText = "Last_Name";
// Add the Columns now
MyGridView.Columns.Add(firstName);
MyGridView.Columns.Add(lastName);
}
NOTE:: FirstName and LastName are the Columns whose Names are passed to the constructor of your custom class: TemplateGenerator.
I have done the same functionality as below with custom paging(using storedProc) for 100+ million records in many tables, update, delete and insert also:
CREATE PROCEDURE [dbo].[sp_Mk]
#PageIndex INT,
#PageSize INT,
#tableName nvarchar(255),
#totalRow INT Output
AS
BEGIN
DECLARE #sql NVARCHAR(MAX)
Declare #anotherSql NVARCHAR(1000)
DECLARE #ParamDefinition NVARCHAR(500)
--DECLARE #totalRow INT
Set #sql = 'WITH TempResult AS( SELECT * FROM '+#tableName+'), TempCount AS ( SELECT COUNT(*) AS MaxRows FROM TempResult )
SELECT * FROM TempResult, TempCount ORDER BY (Select Null)
OFFSET '+CONVERT(VARCHAR(20),(#PageIndex-1)*#PageSize) +' ROWS FETCH NEXT '+CONVERT(VARCHAR(20),#PageSize)+' ROWS ONLY'
PRINT #SQL
EXECUTE sp_executesql #SQL
Set #anotherSql=N'SELECT COUNT(*) as totalRow FROM '+#tableName
SET #ParamDefinition = N'#totalRowOutPut INT OUTPUT'
--PRINT #anotherSql
Execute sp_executesql #anotherSql,
#ParamDefinition,
--#tableNameInput=#tableName,
#totalRowOutPut=#totalRow OUTPUT
End
<asp:GridView CssClass="table-striped header-fixed" ID="grdDynamic" runat="server" AutoGenerateColumns="True" ShowHeaderWhenEmpty="true" AutoGenerateEditButton="true" AutoGenerateDeleteButton="true"
OnRowEditing="OnRowEditing_grdDynamic" OnRowUpdating="OnRowUpdating_grdDynamic" OnRowCancelingEdit="OnRowCancelingEdit_grdDynamic" OnRowDeleting="OnRowDeleting_grdDynamic" OnRowDataBound="OnRowDataBound_grdDynamic">
</asp:GridView><br/>
<asp:linkbutton id="AddButton" runat="server" commandname="Add" text="Insert: " OnClick="AddNewButton_Click" /><br/>
<asp:Repeater ID="rptPager" runat="server">
<ItemTemplate>
<asp:LinkButton ID="lnkPage" CssClass="pagination-ys" runat="server" Text = '<%#Eval("Text") %>' CommandArgument = '<%# Eval("Value") %>' Enabled = '<%# Eval("Enabled") %>' OnClick = "Page_Changed"></asp:LinkButton>
</ItemTemplate>
</asp:Repeater><asp:HiddenField runat="server" id="hdnPageIndex" Value="1"></asp:HiddenField>
SqlConnectionStringBuilder builder;
int pageSize = 100;
protected void Page_Load(object sender, EventArgs e)
{
builder = new SqlConnectionStringBuilder(connectionString);
if (!IsPostBack)
{
using (SqlConnection connObj = new SqlConnection(connectionString))
{
connObj.Open();
using (SqlDataAdapter adapter = new SqlDataAdapter("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_CATALOG='" + builder.InitialCatalog + "' AND TABLE_NAME Not In('AspNetUsers') Order By TABLE_NAME", connObj))
{
DataSet ds = new DataSet();
adapter.Fill(ds);
ddlTableNames.DataSource = ds;
ddlTableNames.DataBind();
ddlTableNames.Items.Insert(0, new ListItem("Select Table", String.Empty));
}
}
}
//}
//else if(ddlTableNames.Visible) ddlTableNames.Visible = false;
}
protected void ddlTableNames_SelectedIndexChanged(object sender, EventArgs e)
{
if (ddlTableNames.SelectedValue != "")
{
grdDynamic.Visible = true;
this.BindGrid(ddlTableNames.SelectedValue, Convert.ToInt32(hdnPageIndex.Value));
}
else if (grdDynamic.Visible == true) grdDynamic.Visible = false;
}
private void BindGrid(string selectedTable, int pageIndex, bool addNewRow=false)
{
using (SqlConnection connObj = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand("sp_Mk", connObj))
{
int recordCount=0;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#PageIndex", pageIndex);
cmd.Parameters.AddWithValue("#PageSize", pageSize);
cmd.Parameters.AddWithValue("#tableName", ddlTableNames.SelectedValue);
SqlParameter totalRow = new SqlParameter("#totalRow", SqlDbType.Int, 4);
totalRow.Direction = ParameterDirection.Output;
cmd.Parameters.Add(totalRow);
connObj.Open();
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
adapter.Fill(ds);
grdDynamic.DataSource = ds.Tables[0];
if (addNewRow) ds.Tables[0].Rows.Add();
recordCount = Convert.ToInt32(ds.Tables[1].Rows[0].ItemArray[0]);
grdDynamic.DataBind();
connObj.Close();
if (totalRow.Value != DBNull.Value)
{
}
this.PopulatePager(recordCount, pageIndex);
}
}
}
private void PopulatePager(int recordCount, int currentPage)
{
double dblPageCount = (double)((decimal)recordCount / pageSize);
int pageCount = (int)Math.Ceiling(dblPageCount);
List<ListItem> pages = new List<ListItem>();
if (pageCount > 0)
{
pages.Add(new ListItem("First", "1", currentPage > 1));
for (int i = 1; i <= pageCount; i++)
{
ListItem item=new ListItem(i.ToString(), i.ToString(), i != currentPage);
if (i == currentPage) item.Attributes.Add("style", "color:red;");
pages.Add(item);
}
pages.Add(new ListItem("Last", pageCount.ToString(), currentPage < pageCount));
}
rptPager.DataSource = pages;
rptPager.DataBind();
}
protected void Page_Changed(object sender, EventArgs e)
{
int pageIndex = int.Parse((sender as LinkButton).CommandArgument);
hdnPageIndex.Value = pageIndex.ToString();
this.BindGrid(ddlTableNames.SelectedValue, pageIndex);
}
protected void OnRowEditing_grdDynamic(object sender, GridViewEditEventArgs e)
{
grdDynamic.EditIndex = e.NewEditIndex;
this.BindGrid(ddlTableNames.SelectedValue, Convert.ToInt32(hdnPageIndex.Value));
}
protected void OnRowUpdating_grdDynamic(object sender, GridViewUpdateEventArgs e)
{
GridViewRow row = grdDynamic.Rows[e.RowIndex];
string updateStatement = string.Empty;
for (int x = 0; x < row.Cells.Count; x++) updateStatement = updateStatement + grdDynamic.DataKeys[e.RowIndex].Values[x] + " = " + grdDynamic.DataKeys[e.RowIndex].Values[x] + ", ";
//int recordId = Convert.ToInt32(grdDynamic.DataKeys[e.RowIndex].Values[0]);
using (SqlConnection con = new SqlConnection(connectionString))
{
//using (SqlCommand cmd = new SqlCommand("UPDATE "+selectedTable"+ SET Name = #Name, Country = #Country WHERE CustomerId = #CustomerId"))
{
cmd.Connection = con;
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
grdDynamic.EditIndex = -1;
this.BindGrid(ddlTableNames.SelectedValue, Convert.ToInt32(hdnPageIndex.Value));
}
protected void OnRowCancelingEdit_grdDynamic(object sender, EventArgs e)
{
grdDynamic.EditIndex = -1;
this.BindGrid(ddlTableNames.SelectedValue, Convert.ToInt32(hdnPageIndex.Value));
}
protected void OnRowDeleting_grdDynamic(object sender, GridViewDeleteEventArgs e)
{
int recordId = Convert.ToInt32(grdDynamic.DataKeys[e.RowIndex].Values[0]);
using (SqlConnection con = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand("DELETE FROM " + ddlTableNames.SelectedValue + " WHERE RecordId = #recordId"))
{
cmd.Connection = con;
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
this.BindGrid(ddlTableNames.SelectedValue, Convert.ToInt32(hdnPageIndex.Value));
}
protected void btnGo_Click(object sender, EventArgs e)
{ int myInt;
if(txtPageSize.Text!=null && txtPageSize.Text !=string.Empty)
if(int.TryParse(txtPageSize.Text, out myInt)) pageSize = myInt;
hdnPageIndex.Value = "1";
this.BindGrid(ddlTableNames.SelectedValue, 1);
}
protected void AddNewButton_Click(object sender, EventArgs e)
{
hdnPageIndex.Value="1";
this.BindGrid(ddlTableNames.SelectedValue, Convert.ToInt32(hdnPageIndex.Value), true);
}
protected void OnRowDataBound_grdDynamic(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow && e.Row.RowIndex != grdDynamic.EditIndex)
{
(e.Row.Cells[0].Controls[2] as LinkButton).Attributes["onclick"] = "return confirm('Do you want to delete this row?');";
}
}
Hope it helps:

how to add footer template dynamically in asp.net

I have created a gridview dynamically. There is template fields described in designing portion. All the columns were created thru code behind as follows. Its works fine. Here I can listed the pages for each rows. But I dont know how to implement the sum of pages in the footer template thru code behind.
TemplateField Pages = new TemplateField();
Pages.HeaderText = "Pages";
Pages.ItemTemplate = new GridViewTemplate_Pages();
gv1.Columns.Add(Pages);
public class GridViewTemplate_Pages : ITemplate
{
void ITemplate.InstantiateIn(Control container)
{
Label PagesLabel = new Label();
PagesLabel.DataBinding += new EventHandler(this.PagesLabel_DataBinding);
container.Controls.Add(PagesLabel);
}
void PagesLabel_DataBinding(object sender, EventArgs e)
{
Label lbl1 = (Label)sender;
GridViewRow row = (GridViewRow)lbl1.NamingContainer;
lbl1.Text = DataBinder.Eval(row.DataItem, "PagesReceived").ToString();
}
}
Given ShowFooter="True" in aspx page and RowDataBound written separately. The following code works fine if I given footer template in aspx page but do not know how to get the result in programmatically. Please advice.
protected void gv1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
int RowTotalPages = Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, "PagesReceived"));
TotalPages = TotalPages + RowTotalPages;
}
if (e.Row.RowType == DataControlRowType.Footer)
{
Label m = (Label)e.Row.FindControl("gv1TotalPages");
m.Text = TotalPages.ToString();
}
}
You can create the footer to a gridview like this.
//Code
GridView gv = new GridView();
gv.RowCreated += delegate(object dsender, GridViewRowEventArgs ge)
{
if (ge.Row.RowType == DataControlRowType.Footer)
ge.Row.Cells[0].Text = "Something";
};
gv.AutoGenerateColumns = false;
gv.ShowFooter = true;
BoundField bf = new BoundField();
bf.HeaderText = "col 1";
bf.DataField = "Length";
gv.Columns.Add(bf);
gv.DataSource = new string[] { "One", "Two", "Three" };
gv.DataBind();
Form.Controls.Add(gv);
This is for the dynamically created gridview and a footer. You can change accordingly.
Its a silly thing. I made it complex. I need the sum of pages in the footer row, then why should I think and confuse about GridViewTemplate and Itemplate class. Simply I added the Total pages in the session and recollect it in the DataControlRowType.Footer. Here is the code:
protected void gv1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
int RowTotalPages = Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, "PagesReceived"));
int RowTotalCharges = Convert.ToInt32(DataBinder.Eval(e.Row.DataItem, "ChargesReceived"));
TotalPages = TotalPages + RowTotalPages;
TotalCharges = TotalCharges + RowTotalCharges;
Session.Add("TotalPages", TotalPages.ToString());
Session.Add("TotalCharges", TotalCharges.ToString());
}
if (e.Row.RowType == DataControlRowType.Footer)
{
e.Row.Cells[4].Text = "Batches Count: " + gv1.Rows.Count.ToString();
e.Row.Cells[5].Text = Session["TotalPages"].ToString();
e.Row.Cells[6].Text = Session["TotalCharges"].ToString();
}
}

Capture DropDownList Index Change event inside of grid View

I am trying to capture the SelectedIndexChanged event for a drop down list I have put inside of a gridview control. It posts back fine, but does not go into my SelectedIndexChanged event handler. Here is my code
DropDownList myddl;
protected void Page_Load(object sender, EventArgs e)
{
this.myGridview.RowDataBound += new GridViewRowEventHandler(myGridview_RowDataBound);
myddl = new DropDownList();
myddl.SelectedIndexChanged += new EventHandler(myddl_SelectedIndexChanged);
if (!Page.IsPostBack)
{
List<Team> teams = giveMeTeams();
this.myGridview.DataSource = teams;
this.myGridview.AutoGenerateColumns = false;
BoundField col1 = new BoundField();
col1.DataField = "Name";
this.myGridview.Columns.Add(col1);
BoundField col2 = new BoundField();
col2.DataField = "Sport";
this.myGridview.Columns.Add(col2);
BoundField col3 = new BoundField();
col3.DataField = "Status";
this.myGridview.Columns.Add(col3);
this.myGridview.DataBind();
}
}
void myGridview_RowDataBound(object sender, GridViewRowEventArgs e)
{
myddl = new DropDownList();
myddl.SelectedIndexChanged += new EventHandler(myddl_SelectedIndexChanged);
List<string> items = new List<string>();
items.Add("good");
items.Add("bad");
myddl.DataSource = items;
myddl.AutoPostBack = true;
myddl.DataBind();
e.Row.Cells[2].Controls.Add(myddl);
}
void myddl_SelectedIndexChanged(object sender, EventArgs e)
{
string temp = "In Here"; //neve hits this code
}
private List<Team> giveMeTeams()
{
Teams teams = new Teams();
teams.Add(new Team("RedWings", "Hockey", "good"));
teams.Add(new Team("Lions", "Football", "bad"));
teams.Add(new Team("Packers", "Football", "good"));
return teams;
}
Any help is greatly appreciated.
Thanks,
Edited based on Comments
I have tried as you suggested...and am still not capturing the post back. here is my new code
void myGridview_RowCreated(object sender, GridViewRowEventArgs e)
{
DropDownList myddl = new DropDownList();
myddl = new DropDownList();
myddl.SelectedIndexChanged += new EventHandler(myddl_SelectedIndexChanged);
myddl.ID = "MyID" + e.Row.RowIndex.ToString();
e.Row.Cells[2].Controls.Add(myddl);
}
void myGridview_RowDataBound(object sender, GridViewRowEventArgs e)
{
DropDownList myddl = e.Row.FindControl("MyID" + e.Row.RowIndex.ToString()) as DropDownList;
//myddl.SelectedIndexChanged += new EventHandler(myddl_SelectedIndexChanged);
List<string> items = new List<string>();
items.Add("good");
items.Add("bad");
myddl.DataSource = items;
myddl.DataMember = "Status";
myddl.AutoPostBack = true;
myddl.DataBind();
e.Row.Cells[2].Controls.Add(myddl);
}
it is still not going into my myddl_SelectedIndexChanged() eventhandler.
Create that Dropdownlist in RowCreated of the Grid and assign an ID to it. Get the refrence to these Dropdowns in RowDataBound via e.Row.FindControl("MyDropdownlistID") and bound them to the Datasource. Create distinct Dropdownlist instances instead of referencing always the same

asp.net - GridView dynamic footer row creation problem

I am able to create BoundFields and Footer-rows dynamically like this in my GridView:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
CreateGridView();
}
}
private void CreateGridView()
{
GridView1.Columns.Clear();
DataTable dataTable = Book.GetBooksDataSet().Tables[0];
CommandField cf = new CommandField();
cf.ShowEditButton = true;
GridView1.Columns.Add(cf);
int colCount = 1;
foreach (DataColumn c in dataTable.Columns)
{
BoundField boundField = new BoundField();
boundField.DataField = c.ColumnName;
boundField.HeaderText = c.ColumnName;
//boundField.FooterText = "---";
if (colCount == 3 || colCount == 5)
{
boundField.ReadOnly = true;
}
GridView1.Columns.Add(boundField);
colCount++;
}
GridView1.ShowFooter = true;
GridView1.DataSource = dataTable;
GridView1.DataBind();
GridViewRow footerRow = GridView1.FooterRow;
Button b = new Button();
b.Text = "Add New";
int i = 0;
footerRow.Cells[i].Controls.Add(b);
foreach (DataColumn c in dataTable.Columns)
{
++i;
TextBox tb = new TextBox();
footerRow.Cells[i].Controls.Add(tb);
}
}
....................................
....................................
....................................
}
But the problem is, when I click the "Add New" - button, it disappears instantly. And, also I am unable to add any event handler to it. Or intercept its actions like this:
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
int index = Convert.ToInt32(e.CommandArgument);
if (e.CommandName == "Edit")
{
GridView1.EditIndex = index;
GridViewRow selectedRow = ((GridView)e.CommandSource).Rows[index];
//We can get cell data like this
string id = selectedRow.Cells[1].Text;
string isbn = selectedRow.Cells[2].Text;
//This is necessary to GridView to be showed up.
CreateGridView();
}
else if (e.CommandName == "Update")
{
LinkButton updateButton = (LinkButton)e.CommandSource;
DataControlFieldCell dcfc = (DataControlFieldCell)updateButton.Parent;
GridViewRow gvr = (GridViewRow)dcfc.Parent;
//The update...................
//Update grid-data to database
UpdateDataInTheDatabase(gvr.Cells[1].Controls);
//Grid goes back to normal
GridView1.EditIndex = -1;
//This is necessary to GridView to be showed up.
CreateGridView();
}
}
One more thing, I have seen some solutions that suggests to handle the GridView's rowBound event. But I need to do it from within Page_load event handler, or in, GridView1_RowCommand event handler.
Dynamically created controls mus be re-created on every postback. Your "Add New" button causes a postback so the dynamically created footer disappears. Is there a reason this grid has to be created dynamically? From the code you posted it appears that you could do this in markup instead. If not, you'll have to re-create the dynamic controls on every postback.
Edited to add:
I played with this a little bit and what's below works in that the grid doesn't disappear and events are handled, but it doesn't actually do anything. Hope this helps.
Markup:
<p><asp:Literal ID="Literal1" runat="server" /></p>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false"
OnRowCommand="GridView1_RowCommand"
OnRowEditing="GridView1_RowEditing"/>
Code:
protected void Page_Load(object sender, EventArgs e)
{
BindGridView();
}
private DataTable GetBooksDataTable()
{
var dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Title", typeof(string));
dt.Columns.Add("Author", typeof(string));
for (int index = 0; index < 10; index++)
{
dt.Rows.Add(index, "Title" + index, "Author" + index);
}
return dt;
}
private void BindGridView()
{
var dt = GetBooksDataTable();
GridView1.Columns.Clear();
GridView1.ShowFooter = true;
var cf = new CommandField();
cf.HeaderText = "Action";
cf.ShowEditButton = true;
GridView1.Columns.Add(cf);
for (int index = 0; index < dt.Columns.Count; index++)
{
var boundField = new BoundField();
boundField.DataField = dt.Columns[index].ColumnName;
boundField.HeaderText = dt.Columns[index].ColumnName;
GridView1.Columns.Add(boundField);
}
GridView1.DataSource = dt;
GridView1.DataBind();
var footer = GridView1.FooterRow;
var b = new LinkButton();
b.Text = "Add New";
b.CommandName = "Add New";
footer.Cells[0].Controls.Add(b);
for (int index = 1; index < dt.Columns.Count + 1; index++)
{
var tb = new TextBox();
footer.Cells[index].Controls.Add(tb);
}
}
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
Literal1.Text = e.CommandName;
}
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
Literal1.Text = "Editing row index " + e.NewEditIndex.ToString();
}
Move your code from Page_Load to Page_Init. Things added in the Page_Load last only for the lifecycle of one postback.
You'd then be able to add eventhandlers, intercept events etc.

GridView Create Fields Dynamically

I would like somebody to help me to solve the following issue.
I have a gridview, where the fields are created dynamically from codebehind.
I would like to create with the same way(dynamically) a templateField which, if it is possible, to hold in it two button controls, having also and commandName.
To be more clear:
Headers-->> First Name, LastName, Print(Daily/Invoices)
Results -->> FooFName, FooLName, Daily | Invoice
The bold one text is what I am looking for.
I am posting also the methods and the way I use them to create the fields.
CreateBoundField(BillingSummaryGV, "Book_Date", "Date", "{0:dd/MM/yyyy}");
CreateButtonField(BillingSummaryGV, "Print", "Print(Daily)", ButtonType.Link,"");
BillingSummaryGV.DataSource = billingSummaries;
BillingSummaryGV.DataBind();
protected void CreateBoundField(GridView gv, string dataField, string headerText, string arrFormatingString) {
var bf = new BoundField {
DataField = dataField,
DataFormatString = arrFormatingString,
HeaderText = headerText
};
gv.Columns.Add(bf);
}
private void CreateButtonField(GridView gv, string text, string headerText, ButtonType buttonType, string commandName) {
var bfPrint = new ButtonField() {
ButtonType = buttonType,
Text = text,
HeaderText = headerText,
Visible = true,
CommandName = commandName
};
gv.Columns.Add(bfPrint);
}
I would appreciate any reply
thanks
You have to create a template class that implements ITemplate. See this example from MSDN. The code below extends my answer to this question to add a template column that displays Title|Author.
Markup:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false"
OnRowCommand="GridView1_RowCommand"
OnRowEditing="GridView1_RowEditing"/>
Code:
protected void Page_Load(object sender, EventArgs e)
{
BindGridView();
}
private DataTable GetBooksDataTable()
{
var dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Title", typeof(string));
dt.Columns.Add("Author", typeof(string));
for (int index = 0; index < 10; index++)
{
dt.Rows.Add(index, "Title" + index, "Author" + index);
}
return dt;
}
private void BindGridView()
{
var dt = GetBooksDataTable();
GridView1.Columns.Clear();
GridView1.ShowFooter = true;
var cf = new CommandField();
cf.HeaderText = "Action";
cf.ShowEditButton = true;
GridView1.Columns.Add(cf);
for (int index = 0; index < dt.Columns.Count; index++)
{
var boundField = new BoundField();
boundField.DataField = dt.Columns[index].ColumnName;
boundField.HeaderText = dt.Columns[index].ColumnName;
GridView1.Columns.Add(boundField);
}
CreateCustomTemplateField(GridView1, "Title|Author");
GridView1.DataSource = dt;
GridView1.DataBind();
var footer = GridView1.FooterRow;
var b = new LinkButton();
b.Text = "Add New";
b.CommandName = "Add New";
footer.Cells[0].Controls.Add(b);
for (int index = 1; index < dt.Columns.Count + 1; index++)
{
var tb = new TextBox();
footer.Cells[index].Controls.Add(tb);
}
}
private void CreateCustomTemplateField(GridView gv, string headerText)
{
var customField = new TemplateField();
customField.HeaderTemplate = new CustomTemplate(DataControlRowType.Header, headerText);
customField.ItemTemplate = new CustomTemplate(DataControlRowType.DataRow, headerText);
gv.Columns.Add(customField);
}
public class CustomTemplate : ITemplate
{
private DataControlRowType _rowType;
private string _headerText;
public CustomTemplate(DataControlRowType rowType, string headerText)
{
_rowType = rowType;
_headerText = headerText;
}
public void InstantiateIn(Control container)
{
switch (_rowType)
{
case DataControlRowType.Header:
var header = new Literal();
header.Text = _headerText;
container.Controls.Add(header);
break;
case DataControlRowType.DataRow:
var data = new Literal();
data.DataBinding += DataRowLiteral_DataBinding;
container.Controls.Add(data);
break;
}
}
private void DataRowLiteral_DataBinding(object sender, EventArgs e)
{
var data = (Literal)sender;
var row = (GridViewRow)data.NamingContainer;
data.Text = DataBinder.Eval(row.DataItem, "Title") + "|" + DataBinder.Eval(row.DataItem, "Author");
}
}
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
Literal1.Text = e.CommandName;
}
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
Literal1.Text = "Editing row index " + e.NewEditIndex.ToString();
}

Resources