主題:GridView動態生成的控件不能觸發OnRowCommand事件,且點擊控件按鈕后,控件的值會消失。
案例,
由於公司需要綁定的數據列順序是動態生成的,且有的數據列需要綁定Button控件。所以需要動態綁定TemplateField。
問題,不能觸發OnRowCommand事件和點擊控件按鈕后,控件的列值會消失。
不能觸發OnRowCommand代碼如下:

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Data; namespace WebApplication1 { public partial class _Default : System.Web.UI.Page { //protected override void OnInit(EventArgs e) //{ // TemplateField customField = new TemplateField(); // customField.ShowHeader = true; // customField.HeaderTemplate = new GridViewTemplate(DataControlRowType.Header, "動態添加列"); // GridViewTemplate gvt = new GridViewTemplate(DataControlRowType.DataRow, "lbtn", "Name"); // customField.ItemTemplate = gvt; // ContactsGridView.Columns.Add(customField);//添加編輯按鈕到gridview //} protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { TemplateField customField = new TemplateField(); customField.ShowHeader = true; customField.HeaderTemplate = new GridViewTemplate(DataControlRowType.Header, "動態添加列"); GridViewTemplate gvt = new GridViewTemplate(DataControlRowType.DataRow, "lbtn", "Name"); customField.ItemTemplate = gvt; ContactsGridView.Columns.Add(customField);//添加編輯按鈕到gridview DataTable dt = new System.Data.DataTable(); dt.Columns.Add("data1"); dt.Columns.Add("ContactID"); DataRow dr = dt.NewRow(); dr["data1"] = "test"; dr["ContactID"] = "ContactID"; dt.Rows.Add(dr); DataRow dr2 = dt.NewRow(); dr2["data1"] = "test2"; dr2["ContactID"] = "ContactID"; dt.Rows.Add(dr2); ContactsGridView.DataSource = dt; ContactsGridView.DataBind(); } } public class GridViewTemplate : ITemplate { public delegate void EventHandler(object sender, EventArgs e); public event EventHandler eh; private DataControlRowType templateType; private string columnName; private string controlID; public GridViewTemplate(DataControlRowType type, string colname) { templateType = type; columnName = colname; } public GridViewTemplate(DataControlRowType type, string controlID, string colname) { templateType = type; this.controlID = controlID; columnName = colname; } public void InstantiateIn(System.Web.UI.Control container) { switch (templateType) { case DataControlRowType.Header: LinkButton lc = new LinkButton(); lc.Text = columnName; container.Controls.Add(lc); break; case DataControlRowType.DataRow: LinkButton lbtn = new LinkButton(); lbtn.ID = "id1"; lbtn.Text = "test"; // lbtn.ID = this.controlID; //if (eh != null) //{ // lbtn.Click += new System.EventHandler(eh); //} // lbtn.DataBinding += new System.EventHandler(lbtn_DataBinding); container.Controls.Add(lbtn); break; default: break; } } } protected void ContactsGridView_OnRowDataBound(Object sender, GridViewRowEventArgs e) { if (e.Row.RowType==DataControlRowType.DataRow) { LinkButton lb = e.Row.FindControl("id1") as LinkButton; lb.CommandArgument = "1"; } } protected void ContactsGridView_RowCommand(Object sender, GridViewCommandEventArgs e) { // If multiple buttons are used in a GridView control, use the // CommandName property to determine which button was clicked. if (e.CommandName == "Add") { // Convert the row index stored in the CommandArgument // property to an Integer. int index = Convert.ToInt32(e.CommandArgument); // Retrieve the row that contains the button clicked // by the user from the Rows collection. GridViewRow row = ContactsGridView.Rows[index]; // Create a new ListItem object for the contact in the row. ListItem item = new ListItem(); item.Text = Server.HtmlDecode(row.Cells[2].Text) + " " + Server.HtmlDecode(row.Cells[3].Text); } } } }
后來把數據綁定從Page.IsPostBack移出,是可以觸發OnRowCommand事件。但是點擊的時候都要重新做GridView的查詢,效率會比較差。

protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { } TemplateField customField = new TemplateField(); customField.ShowHeader = true; customField.HeaderTemplate = new GridViewTemplate(DataControlRowType.Header, "動態添加列"); GridViewTemplate gvt = new GridViewTemplate(DataControlRowType.DataRow, "lbtn", "Name"); customField.ItemTemplate = gvt; ContactsGridView.Columns.Add(customField);//添加編輯按鈕到gridview DataTable dt = new System.Data.DataTable(); dt.Columns.Add("data1"); dt.Columns.Add("ContactID"); DataRow dr = dt.NewRow(); dr["data1"] = "test"; dr["ContactID"] = "ContactID"; dt.Rows.Add(dr); DataRow dr2 = dt.NewRow(); dr2["data1"] = "test2"; dr2["ContactID"] = "ContactID"; dt.Rows.Add(dr2); ContactsGridView.DataSource = dt; ContactsGridView.DataBind(); }
最終解決方法,
1.用BoundField替代TemplateField方法,代碼如下。
ButtonField adup = new ButtonField(); adup.ButtonType = ButtonType.Link; adup.HeaderText = "廣告上架"; adup.Text = "test"; adup.CommandName = "shangjia"; ContactsGridView.Columns.Add(adup);//添加編輯按鈕到gridview
2.重新寫OnInit方法。在OnInit上綁定TemplateField,可以觸發OnRowCommand事件。
protected override void OnInit(EventArgs e) { TemplateField customField = new TemplateField(); customField.ShowHeader = true; customField.HeaderTemplate = new GridViewTemplate(DataControlRowType.Header, "動態添加列"); GridViewTemplate gvt = new GridViewTemplate(DataControlRowType.DataRow, "lbtn", "Name"); customField.ItemTemplate = gvt; ContactsGridView.Columns.Add(customField);//添加編輯按鈕到gridview }
2,
動態綁定控件不能觸發的估計原因是:
1)用TemplateField動態綁定的控件不是服務器端控件,不在ViewState記錄,所以刷新頁面后,這些列的值會消失,OnRowCommand事件自然也不會觸發。
2)而用BoundField,會記錄ViewState,所以刷新頁面后,就會觸發事件OnRowCommand。
3)在OnInit上綁定控件,首先會初始化綁定控件和事件(OnRowCommand重新綁定了)。這樣OnRowCommand事件也會觸發。