主题: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事件也会触发。