• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1409
  • Last Modified:

Why does DataGrid lose ItemCommand event after postback

Should I have to rebind a datagrid for its events to fire?

If I  DataBind the grid every page load, the ItemCommand Event fires no problem.  If I don't databind, it wont' fire.  I thought that DataBinding flushed out the event list of the datagrid!  What's the correct way to use this control?


I've got the following code:

public class testgrid : System.Web.UI.Page
      {
            protected System.Web.UI.WebControls.DataGrid DataGrid1;
      
            private void Page_Load(object sender, System.EventArgs e)
            {
                  LoadGrid();

                  // Works
                  BindData(DataGrid1);

                  // Doesn't work
                  // if(!Page.IsPostBack)
                  //       BindData(DataGrid1);
            }

            private void LoadGrid()
            {
                  DataGrid1.ItemCommand += new DataGridCommandEventHandler(DataGrid1_ItemCommand);

                  ButtonColumn bc = new ButtonColumn();
                  bc.CommandName = "Edit";
                  bc.DataTextField = "UserID";

                  BoundColumn user = new BoundColumn();
                  user.DataField = "UserName";
                  user.HeaderText = "User";

                  DataGrid1.Columns.Add(bc);
                  DataGrid1.Columns.Add(user);

                  DataGrid1.DataSource = DbWrapper.ExecuteDataSet("select * from _Users where userid < 1000");

            }

            private void BindData(DataGrid g)
            {
                  g.DataBind();
            }

            private void DataGrid1_ItemCommand(object sender, DataGridCommandEventArgs e)
            {
                  switch(e.CommandName)
                  {
                        case "Edit":
                              break;
                        default:
                              break;
                  }
            }

      }

L'Ordinateur
0
lordinateur
Asked:
lordinateur
  • 8
  • 5
  • 4
  • +1
1 Solution
 
mmarinovCommented:
you have to bind data to datagrid after each operation
0
 
JasonRichardCommented:
Not really sure why this isn't working for you.  Try using the DataGrid1.DataBind() method within LoadGrid.

if(!Page.IsPostBack)
{
      LoadGrid();
}

private void LoadGrid()
{
      ButtonColumn bc = new ButtonColumn();
      bc.CommandName = "Edit";
      bc.DataTextField = "UserID";

      BoundColumn user = new BoundColumn();
      user.DataField = "UserName";
      user.HeaderText = "User";

      DataGrid1.Columns.Add(bc);
      DataGrid1.Columns.Add(user);

      DataGrid1.DataSource = DbWrapper.ExecuteDataSet("select * from _Users where userid < 1000");

      DataGrid1.DataBind();
}


As for the line of code below, I don't think you need it in the code behind file (whatever.aspx.cs).
DataGrid1.ItemCommand += new DataGridCommandEventHandler(DataGrid1_ItemCommand);

Just do this as an attribute of the DataGrid tag of the code file (whatever.aspx)

<asp:DataGrid ID="DataGrid1" ... OnItemCommand="DataGrid1_ItemCommand">

0
 
JasonRichardCommented:
Oops...Postback check needs to be in the Page_Load method.

private void Page_Load(object sender, System.EventArgs e)
{
    if(!Page.IsPostBack)
    {
        LoadGrid();
    }
}
0
Become an Android App Developer

Ready to kick start your career in 2018? Learn how to build an Android app in January’s Course of the Month and open the door to new opportunities.

 
lordinateurAuthor Commented:
Thank you for you reply, Jason.  

I tried to just add the OnItemCommand event in the aspx file and I get an error stating that the _ItemCommand method is inaccessible due to its protection level.  It apparently wants me to make this method protected rather than private.  Why??

At any rate, your suggestions don't seem to retain the event either.  Can anybody get the code I posted to work properly?  That is, not require another databind to retain events.
0
 
JasonRichardCommented:
You need to make the method public, private methods can only be accessed within the class itself.

public void DataGrid1_ItemCommand(object sender, DataGridCommandEventArgs e)
{
}
0
 
mmarinovCommented:
i think that the problem is not in the Page_load.
the problem is after your first databinding
when itemcommand fires you don't bind the datagrid

you have to write this

 private void DataGrid1_ItemCommand(object sender, DataGridCommandEventArgs e)
          {
               switch(e.CommandName)
               {
                    case "Edit":
                         break;
                    default:
                         break;
BindData(DataGrid1);

               }

          }

and in the Page_load write just
if(!Page.IsPostBack)
  BindData(DataGrid1);
0
 
lordinateurAuthor Commented:
I don't want to make the event methods public or protected.  I don't see why I shouldn't be able to do all this in the code-behind.  

mmarinov: I don't think that's it.  I never even get into the ItemCommand event so I can't bind the data again there.  It works just fine if I bind the data in Page_Load but I don't want to make more round trips to the datasource than I need to.


Maybe this is harder than I thought it would be...I'm increasing the points on this question to 300.

0
 
JasonRichardCommented:
I ran into problems when I tried to do everything in code behind as well, it is more confusing.
0
 
lordinateurAuthor Commented:
I come from a non-ASP background so I'm inclined to think the opposite, I prefer working in the code-behind.  

It is more confusing...but it shouldn't be.  As far as I've gathered, the page life-cycle should be able to recognize and rebuild the state of any controls you add but in practice this is harder than it sounds.  Anything created dynamically has been a crapshoot.
0
 
mmarinovCommented:
So i've try the code and everything works fine
When you use
if(!Page.IsPostBack)
 BindData(DataGrid1);

the datagrid is binded in the first time but when you want to fire up the ItemCommand nothing happend because in the ItemCommand function you don't bind the datagrid again. all the stuff you want to do in the ItemCommand is done but it is not shown because the datagrid is not binded

After the ItemCommand is executed once nothing will happen

B..G
0
 
lordinateurAuthor Commented:
I don't understand how you got it to work.  Can you post the exactly what you have?  When I run the following code, it never enters the itemcommand method:


public class testgrid : System.Web.UI.Page
      {
            protected System.Web.UI.WebControls.DataGrid DataGrid1;
      
            private void Page_Load(object sender, System.EventArgs e)
            {
                  
                  LoadGrid();
                  if(!Page.IsPostBack)
                        BindData(DataGrid1);
                        
            }

            private void LoadGrid()
            {
                  
                  ButtonColumn bc = new ButtonColumn();
                  bc.CommandName = "Edit";
                  bc.DataTextField = "UserID";

                  BoundColumn user = new BoundColumn();
                  user.DataField = "UserName";
                  user.HeaderText = "User";

                  DataGrid1.Columns.Add(bc);
                  DataGrid1.Columns.Add(user);

                  DataGrid1.DataSource = DbWrapper.ExecuteDataSet("select * from rz_User where userid < 1011");

                  
            }

            private void BindData(DataGrid g)
            {
                  g.DataBind();
            }

            private void DataGrid1_ItemCommand(object sender, DataGridCommandEventArgs e)
            {
                  switch(e.CommandName)
                  {
                        case "Edit":
                              break;
                        default:
                              break;
                  }
                  BindData(DataGrid1);
            }

            #region Web Form Designer generated code
            override protected void OnInit(EventArgs e)
            {
                  //
                  // CODEGEN: This call is required by the ASP.NET Web Form Designer.
                  //
                  InitializeComponent();
                  base.OnInit(e);
            }
            
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {  
                  DataGrid1.ItemCommand += new DataGridCommandEventHandler(DataGrid1_ItemCommand);
                  this.Load += new System.EventHandler(this.Page_Load);

            }
            #endregion
      }
}
0
 
lordinateurAuthor Commented:
this is what I have in my aspx page



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
      <HEAD>
            <title>testgrid</title>
            <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
            <meta name="CODE_LANGUAGE" Content="C#">
            <meta name="vs_defaultClientScript" content="JavaScript">
            <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
      </HEAD>
      <body MS_POSITIONING="GridLayout">
            <form id="Form1" method="post" runat="server">
                  <asp:DataGrid id="DataGrid1" style="Z-INDEX: 101; LEFT: 32px; POSITION: absolute; TOP: 48px" runat="server"
                        AutoGenerateColumns="False"></asp:DataGrid>
            </form>
      </body>
</HTML>
0
 
mmarinovCommented:
here is the html

<asp:DataGrid OnItemCommand="DataGrid1_ItemCommand" PagerStyle-Visible="False" ShowFooter="False"                     AutoGenerateColumns="False" AllowCustomPaging="False" AllowPaging="True" id="DataGrid1" style="Z-INDEX: 103" runat="server">
                    <Columns>
                         <asp:BoundColumn DataField="ID1" HeaderText="Attribute" SortExpression="STRING"/>
                         <asp:TemplateColumn HeaderText="VALUE">
                              <ItemTemplate>
                                   <asp:TextBox Runat="server" ID="Textbox1">name</asp:TextBox>
                              </ItemTemplate>
                         </asp:TemplateColumn>
                         <asp:ButtonColumn CommandName="update" ButtonType="PushButton" Text="Update"></asp:ButtonColumn>
                    </Columns>
               </asp:DataGrid>

here is the code behind

public class testgrid : System.Web.UI.Page
{
      protected System.Web.UI.WebControls.DataGrid DataGrid1;
     
      private void Page_Load(object sender, System.EventArgs e)
      {
            LoadGrid();

             if(!Page.IsPostBack)
                  BindData(DataGrid1);
      }

      private void LoadGrid()
      {
            ButtonColumn bc = new ButtonColumn();
            bc.CommandName = "Edit";
            bc.DataTextField = "ID1";

            BoundColumn user = new BoundColumn();
            user.DataField = "UserName";
            user.HeaderText = "User";

            DataGrid1.Columns.Add(bc);
            DataGrid1.Columns.Add(user);


            DataSet ds = new DataSet();
            ds.Tables.Add("aaa");
            ds.Tables[0].Columns.Add("ID1");
            ds.Tables[0].Columns.Add("UserName");

            DataRow dr = ds.Tables[0].NewRow();
            dr[0] = "first custom value";
            dr[1] = "second custom value" ;

            ds.Tables[0].Rows.Add( dr );

            DataGrid1.DataSource = ds ;

      }

      private void BindData(DataGrid g)
      {
            g.DataBind();
      }

      protected void DataGrid1_ItemCommand(object sender, DataGridCommandEventArgs e)
      {
            switch(e.CommandName)
            {
                  case "Edit":
                        break;
                  default:
                        break;
            }
            BindData ( DataGrid1 );
      }

      #region Web Form Designer generated code
      override protected void OnInit(EventArgs e)
      {
            //
            // CODEGEN: This call is required by the ASP.NET Web Form Designer.
            //
            InitializeComponent();
            base.OnInit(e);
      }
            
      /// <summary>
      /// Required method for Designer support - do not modify
      /// the contents of this method with the code editor.
      /// </summary>
      private void InitializeComponent()
      {    
            this.Load += new System.EventHandler(this.Page_Load);

      }
      #endregion
0
 
lordinateurAuthor Commented:
Hmm, this is pretty interesting.  I was able to get your code to work but the difference with mine is that I am doing all the column creation in the code behind.  I don't see why this would make a difference considering that I do it on every page load.  

At any rate, if I combine the two techniques, (some declared in aspx page, some in code-behind), if I click on the parts of the DataGrid that were declared in the aspx page, it's fine--itemcommand fires and state is maintained.  However, when I click the columns of the datagrid that I added in the code-behind, the itemcommand does not fire.  And, because I'm not rebinding on Postback I guess, those columns actually disaapear from the datagrid.

Why should one technique work and the other not?
0
 
lordinateurAuthor Commented:
Ok, here's the answer, thanks to Scott Mitchell:

whenever you add controls dynamically to an ASP.NET Web page, you have to always recreate the controls upon postback, otherwise they will be lost.
 
So, all you need to do is recreate the columns, regardless of its a postback or not.  Now, this needs to happen BEFORE the ViewState is loaded, so do it in the Page_Init event handler.

------

The problem was that I wasn't recreating the columns in the Page_Init event.
0
 
mmarinovCommented:
great, you find the answer
B..G
0
 
lordinateurAuthor Commented:
Yes, thanks for your help.

L
0
 
SpazMODicCommented:
PAQed, with points refunded (300)

SpazMODic
EE Moderator
0

Featured Post

Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

  • 8
  • 5
  • 4
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now