user1301708
user1301708

Reputation: 191

RowCommand not firing

I am trying to programmatically add a button in ASP.NET with C# as the backend. I am able to display the button, but the RowCommand isn't getting fired when the user clicks the button.

I believe the problem is that I am creating the buttons after the user clicks on a "Submit" button. If I make the button in the page_load then the RowCommand works.

This is how the website should flow:

  1. Page load: display basic data.
  2. User clicks on a Submit button which creates a GridView, which has a ButtonField. Both the GridView and the ButtonField get created dynamically on the backend.
  3. User then clicks on the generated Button and it should fire the RowCommand

Here is the code:

Page_load

protected void Page_Load(object sender, EventArgs e)
    {
     //Nothing because we only want to create the button after the user
     //clicks on submit   
    }

randomGridView

Generates the Gridviews and buttons

public void randomGridView(Table t, int x)
    {

        GridView gv1 = new GridView();
        GridView gv2 = new GridView();
        GridView gv3 = new GridView();
        GridView gv4 = new GridView();

        TableRow r = new TableRow();
        for (int i = 0; i < x; i++)
        {
            TableCell c = new TableCell();
            c.BorderStyle = BorderStyle.Solid;
            if (i == 0)
            {
                c.Controls.Add(gv1);
            }
            if (i == 1)
            {
                c.Controls.Add(gv2);
            }
            if (i == 2)
            {
                c.Controls.Add(gv3);
            }
            if (i == 3)
            {
                c.Controls.Add(gv4);
            }
            r.Cells.Add(c);
        }
        t.Rows.Add(r);

        //Where the xml gets bonded to the data grid
        XmlDataSource xds = new XmlDataSource();

        xds.Data = xml;
        xds.DataBind();
        xds.EnableCaching = false;

        gv1.DataSource = xds;

        ButtonField temp = new ButtonField();
        temp.ButtonType = ButtonType.Image;
        temp.ImageUrl = "~/checkdailyinventory.bmp";
        temp.CommandName = "buttonClicked";
        temp.HeaderText = " ";
        gv1.Columns.Add(temp);

        gv1.RowCommand += new GridViewCommandEventHandler(CustomersGridView_RowCommand);
        gv1.RowDataBound += new GridViewRowEventHandler(inventoryGridView_RowDataBound);
        gv1.DataBind();

        xds.Data = xml;
        xds.DataBind();
        xds.EnableCaching = false;

        gv2.DataSource = xds;
        gv2.DataBind();


        xds.Data = xml;
        xds.DataBind();
        xds.EnableCaching = false;

        gv3.DataSource = xds;
        gv3.DataBind();

        xds.Data = xml;
        xds.DataBind();
        xds.EnableCaching = false;

        gv4.DataSource = xds;
        gv4.DataBind();
    }

inventoryGridView_RowDataBound

Where I tried manaully adding a button to the first cell

public void inventoryGridView_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        Button temp = new Button();
        temp.CommandName = "buttonClicked";
        temp.Text = "temp button!";
        e.Row.Cells[0].Controls.Add(temp);
    }

CustomersGridView_RowCommand

This is what needs to get fired

public void CustomersGridView_RowCommand(Object sender, GridViewCommandEventArgs e)
    {
        if (e.CommandName == "buttonClicked")
        {
            int index = Convert.ToInt32(e.CommandArgument);
            Label1.Text = index.ToString();

        }
    }

Button1_Click

What actually creates the gridviews and the buttons

public void Button1_Click(object sender, EventArgs e)
    {
        randomGridView(Table1, 1);
        randomGridView(Table2, 4);
    }

So how do I get the button to fire CustomersGridView_RowCommand? Or is it impossible to link a dynamically generated button?

Edit: Here is the ASPX Page:

        <table>
            <tr>
                <td>
                    <div id="div1" style="width: 257px; height: 500px; overflow-x: scroll; overflow-y: hidden;">
                        <asp:Table ID="Table1" runat="server">
                        </asp:Table>
                    </div>
                </td>
                <td>
                    <div id="div2" style="width: 500px; height: 500px; overflow: scroll;">
                        <asp:Table ID="Table2" runat="server">
                        </asp:Table>
                    </div>
                </td>
            </tr>
        </table>

Upvotes: 1

Views: 3446

Answers (2)

user1301708
user1301708

Reputation: 191

I was finally able to get the RowCommand to fire after dynamically creating it. Here is my solution although I cannot say this is the best way of doing things:

protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);

        if (IsPostBack){
            if (Request.Form[Button1.UniqueID] != null)
            {
                //Get the data from the server
                randomGridView(Table1, 1);
                randomGridView(Table2, 4);
            }
            //Just display the form here



        }
    }

Now instead of waiting till I get to the button_click event I check in OnInit if the button was clicked. If it was then I know the user wants me to load the data and display it. Currently in the code above I just make and display data in the same function (Which is a bad design, but I was just simply prototyping).

Then whenever the user clicks on anything that will cause a postback it will then add the table to the controls. Then the controls can fire (I have no idea why or how, but it works..)

Just to show that we don't even need a button function:

        public void Button1_Click(object sender, EventArgs e)
    {
        //randomGridView(Table1, 1);
        //randomGridView(Table2, 4);
        //Session.Add("doIt",true);
    }

Again this probably isn't the best way of doing things, but it works. If someone has a better solution please let me know.

Upvotes: 1

Alan McBee
Alan McBee

Reputation: 4320

It's not impossible. You need to understand that the control tree (which you supplement with your randomGridView method) is rebuilt automatically when the page is re-loaded from view state, but the event handlers for those dynamically added controls are NOT rebuilt automatically.

In particular, this line which attaches the event handler:

gv1.RowCommand += new GridViewCommandEventHandler(CustomersGridView_RowCommand); 

is NOT getting re-executed when you page reloads from view state, which it must do when you click on one of the buttons in the grid and the browser posts the page back to the server.

Your solution will be to check the page for a postback condition in the Load event phase. If Page.IsPostBack is true, scan your control tree for these dynamically generated grids, and set event handlers (like the code above) for the RowCommand event.

Upvotes: 3

Related Questions