Solved

Why does DataGrid lose ItemCommand event after postback

Posted on 2003-11-24
19
1,393 Views
Last Modified: 2011-10-03
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
Comment
Question by:lordinateur
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 5
  • 4
  • +1
19 Comments
 
LVL 28

Expert Comment

by:mmarinov
ID: 9813919
you have to bind data to datagrid after each operation
0
 

Expert Comment

by:JasonRichard
ID: 9814070
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
 

Expert Comment

by:JasonRichard
ID: 9814098
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
More Than Just A Video Library

Train for your certification. Learn the latest DevOps tools. Grow your skillset to do better work.

At Linux Academy, we release new training modules every week so you'll always be up to date on the latest tech.

 

Author Comment

by:lordinateur
ID: 9814217
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
 

Expert Comment

by:JasonRichard
ID: 9814350
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
 
LVL 28

Expert Comment

by:mmarinov
ID: 9814366
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
 

Author Comment

by:lordinateur
ID: 9814448
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
 

Expert Comment

by:JasonRichard
ID: 9814453
I ran into problems when I tried to do everything in code behind as well, it is more confusing.
0
 

Author Comment

by:lordinateur
ID: 9814477
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
 
LVL 28

Expert Comment

by:mmarinov
ID: 9814514
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
 

Author Comment

by:lordinateur
ID: 9814719
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
 

Author Comment

by:lordinateur
ID: 9814737
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
 
LVL 28

Expert Comment

by:mmarinov
ID: 9814756
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
 

Author Comment

by:lordinateur
ID: 9817545
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
 

Author Comment

by:lordinateur
ID: 9866923
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
 
LVL 28

Expert Comment

by:mmarinov
ID: 9867029
great, you find the answer
B..G
0
 

Author Comment

by:lordinateur
ID: 9867183
Yes, thanks for your help.

L
0
 

Accepted Solution

by:
SpazMODic earned 0 total points
ID: 9888016
PAQed, with points refunded (300)

SpazMODic
EE Moderator
0

Featured Post

Instantly Create Instructional Tutorials

Contextual Guidance at the moment of need helps your employees adopt to new software or processes instantly. Boost knowledge retention and employee engagement step-by-step with one easy solution.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

It seems a simple enough task, yet I see repeated questions asking how to do it: how to pass data between two forms. In this article, I will show you the different mechanisms available for you to do just that. This article is directed towards the .N…
In my previous article (http://www.experts-exchange.com/Programming/Languages/.NET/.NET_Framework_3.x/A_4362-Serialization-in-NET-1.html) we saw the basics of serialization and how types/objects can be serialized to Binary format. In this blog we wi…
If you're a developer or IT admin, you’re probably tasked with managing multiple websites, servers, applications, and levels of security on a daily basis. While this can be extremely time consuming, it can also be frustrating when systems aren't wor…
Monitoring a network: why having a policy is the best policy? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the enormous benefits of having a policy-based approach when monitoring medium and large networks. Software utilized in this v…

726 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question