locked
Dynamically generated image button's OnClick RRS feed

  • Question

  • User-39953368 posted

    Hi,

    can I assign a n OnClick event to a dymanically generated image button? InteliSense does not show this event.

    I use this image button in a dynamically generated table cell (trash can image) and want to be able to delete the row of the table when the image is clicked.

    TableCell tCell5 = new TableCell();

    ImageButton imgDel = new ImageButton();

    imgDel.ID = "ib" + id;  // "id" is id of a hashtable entry:  htProducts.Add(id, qty);imgDel.ImageUrl = "~/assets/images/icons/trash_can.gif";

    tCell5.Controls.Add(imgDel);

    tRow.Cells.Add(tCell5);

    How can I assign the event to the button and what do I need to do to deletethe row when the image is clicked?

    Thanks.

    Tuesday, July 3, 2007 1:57 PM

Answers

  • User2064313513 posted

    Alright ill try to make this clear :S. lets say for example that you have buttons you want to create dynamically, which i believe you do. Now these buttons are not made on page_load, they are made when a user clicks something like "show advanced options" in your table. This would normally go out, call a function and draw buttons onto your table, but like we found out, no events will work. so here is what i woud do. first make a nice little if(ispostback) statment like this.

            if(IsPostBack)
            {
                if (ViewState.Count > 0)
                {
                    if (ViewState["drawButtons"] == "true")
                    {
                        //Get out buttons that we want to draw
                        Button myButton = getButton();
    
                        //We add the event here, because its in page_load it will fire
                        myButton.Click += new EventHandler(this.myButton_Click);
    
                        //This is where we are actually going to draw the buttons
                        //You might want to put it somehwere else, I happen to have an 
                        //update panel on the main form that i am going to put them in
                        updater.ContentTemplateContainer.Controls.Add(myButton);
                    }
                }
            }

     now it is set up so that instead of the buttons being draw when the users clicks on another buttons, they are drawn when certain criteria is met. Now all we have to do is set this criteria to make this all happen, at the point where we used to create the buttons. so say we have a button before called "show advanced features" that called a function drawButtons. Instead of that function drawing to our table, all we need for it to do now is set a viewstate property and post back so I just linked the show features button to a drawButtons.click event

        private void drawButtons_Click(object sender, EventArgs e)
        {
            ViewState["drawButtons"] = "true";
        }

     now when the user clicks this it will post back, the page_load will see the post back, see that there are more then 0 viewStates, see that this one is true, and then work through the code to add the buttons. This example isnt really pratical but it might help you understand. because my page was complicated i had to set more then just 1 view state, i had about 3, one saying what kind of button to add (save, edit, add), what table to add it to, and what event to tie it to. then in the postback using case and if statments i sorted it all out and got the events working.

    I hope that my rambeling isnt confussing.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, July 4, 2007 4:13 PM

All replies

  • User2064313513 posted

    Where you define your button you can also define a link to an event handler

    //Add new click event for image button
    imgDel.Click += new EventHandler(this.imgDel_Click);
    
    
     then later on your can write a function to act as event handler 
    private void imgDel_Click(object sender, EventArgs e)
    {
        //This is where the code goes that you want to happen
        //When the button is clicked
    
        //This is an example of how i would remove the row this button is in
        yourTable.Rows.Remove(((TableRow)sender).Parent.Parent);
    
        //((TableRow)sender).Parent.Parent takes our sender, in this case
        //the image button, finds its first parent, from what i can tell
        //its first parent is a table cell. and then gets the parent of 
        //that table cell, which should be a table row. Then takes that row
        //And passes it into the row remove function
    }
    
     
    Tuesday, July 3, 2007 2:13 PM
  • User955742345 posted

    Because an ImageButton is being used, you need a different event handler and event args for your event:

     

    //code to create the ImageButton
    ImageButton i = new ImageButton();
    i.Click += new ImageClickEventHandler(ImageBtn_Click);
    
    
    
    
    
    //the event handler
    protected void ImageBtn_Click(object sender, ImageClickEventArgs e)
    {
      //do stuff.
    }
     
    Tuesday, July 3, 2007 2:16 PM
  • User-39953368 posted

    Thanks for the info. I get an error message:

    imgDel.Click += new EventHandler(this.imgDel_Click);
    No overlaod for 'imgDel_Click' matches delegate 'System.EventHandler'

    ( I also had to change:

    YourTable.Rows.Remove(((TableRow)sender).Parent.Parent))

    to

    YourTable.Rows.Remove((TableRow)((ImageButton)sender).Parent.Parent); )

    Thanks.

    Tuesday, July 3, 2007 2:32 PM
  • User2064313513 posted

    my bad

    imgDel.Click += new ImageClickEventHandler(this.imgDel_Click);

    Tuesday, July 3, 2007 2:38 PM
  • User-39953368 posted

    Thank you.

    The event does not get fired when I click on the image. What I am trying to do is to allow user to select a product from a drop down list and other properties (such as quantity, ...). There is a button that when clicked will display the the list of products seected so far, in a dynamically generated table. The last column of each row in the table has the image of a trash can that should delete its corresponding row. I used a hashtable to store id/qty pairs. The dropdown list is ddlProd and quantity textbox is tbQty. The button that is supposed to pupdate the table content is ibMore with the Click event of ibMore_Click().

    public partial class NewPackage : System.Web.UI.Page {

    public Hashtable htProducts {

    get {

    if (ViewState["htProducts"] == null) {  ViewState["htProducts"] = new Hashtable();

    }

    return ViewState["htProducts"] as Hashtable;

    }

    }

    protected void ibMore_Click(object sender, ImageClickEventArgs e) {

    int id = Convert.ToInt32(ddlProd.SelectedValue);

    string dev_name = ddlProd.SelectedItem.ToString();

    int qty = int.Parse(tbQty.Text);

    htProducts.Add(id, qty);

    Table tblDevices;if (Session["tbDevices"] != null)

    {

    tblDevices = (
    Table)Session["tbDevices"];

    }

    else 

    {

    tblDevices =
    new Table();

    tblDevices.CssClass = "tblPackage";

    TableHeaderRow tHead = new TableHeaderRow();

    tblDevices.Rows.Add(tHead);

    TableHeaderCell tHead1 = new TableHeaderCell();

    tHead1.Text = "Device";

    tHead1.Width = Unit.Pixel(250);

    tHead.Cells.Add(tHead1);

    TableHeaderCell tHead2 = new TableHeaderCell();

    tHead2.Text = "Qty";

    tHead2.Width = Unit.Pixel(70);

    tHead.Cells.Add(tHead2);

    TableHeaderCell tHead5 = new TableHeaderCell();

    tHead5.Text = "Delete";

    tHead5.Width = Unit.Pixel(100);

    tHead.Cells.Add(tHead5);

    }

    TableRow tRow = new TableRow();

    tblDevices.Rows.Add(tRow);

    TableCell tCell1 = new TableCell();

    tCell1.Text = dev_name;

    tRow.Cells.Add(tCell1);

    TableCell tCell2 = new TableCell();

    tCell2.Text = qty.ToString();

    tRow.Cells.Add(tCell2);

    TableCell tCell5 = new TableCell();ImageButton imgDel = new ImageButton();

    imgDel.ID = id.ToString();

    imgDel.ImageUrl = "~/assets/images/icons/trash_can.gif";

    imgDel.Click += new ImageClickEventHandler(this.imgDel_Click);

    tCell5.Controls.Add(imgDel);

    tRow.Cells.Add(tCell5);

    Session[
    "tbDevices"] = tblDevices;

    phDevices.Controls.Add(tblDevices);

    }

    protected void imgDel_Click(object sender, ImageClickEventArgs e)   // I put a breakpoint here, but the code does not get here

    {

    ImageButton ibDel = (ImageButton)sender;

    Table tblDevices = (Table)Session["tbDevices"];

    tblDevices.Rows.Remove((TableRow)ibDel.Parent.Parent);

    int id = Convert.ToInt32(ibDel.ID);

    htProducts.Remove(id);

    }

    Wednesday, July 4, 2007 2:24 PM
  • User-274385652 posted

    It seems you have run into the same issue that I've been having (and posted about a few days ago): if you don't assign the dynamic control and event handler in the Page_Load event, the event handler is never called. I've not found a way around this yet, sadly.

    Wednesday, July 4, 2007 2:35 PM
  • User2064313513 posted

    there is no real straight up way around this, its just the way the page lifecycle works. One way that I got around this was on the click of my button that initiated the code to make my other buttons and their click events, instead of going right to those declirations, i save values into ViewStates. Then i didnt a async postback and in the page_load function check to see if those viewState values were there. If so i would take those values (the ids of the buttons) and link them to the event for their .click action. This was the events are being set at page load and all is well. its a little confussing at first but now it works great

    Wednesday, July 4, 2007 2:42 PM
  • User-39953368 posted

    Can you post a small sample code on how this is done?

    Wednesday, July 4, 2007 3:17 PM
  • User2064313513 posted

    Alright ill try to make this clear :S. lets say for example that you have buttons you want to create dynamically, which i believe you do. Now these buttons are not made on page_load, they are made when a user clicks something like "show advanced options" in your table. This would normally go out, call a function and draw buttons onto your table, but like we found out, no events will work. so here is what i woud do. first make a nice little if(ispostback) statment like this.

            if(IsPostBack)
            {
                if (ViewState.Count > 0)
                {
                    if (ViewState["drawButtons"] == "true")
                    {
                        //Get out buttons that we want to draw
                        Button myButton = getButton();
    
                        //We add the event here, because its in page_load it will fire
                        myButton.Click += new EventHandler(this.myButton_Click);
    
                        //This is where we are actually going to draw the buttons
                        //You might want to put it somehwere else, I happen to have an 
                        //update panel on the main form that i am going to put them in
                        updater.ContentTemplateContainer.Controls.Add(myButton);
                    }
                }
            }

     now it is set up so that instead of the buttons being draw when the users clicks on another buttons, they are drawn when certain criteria is met. Now all we have to do is set this criteria to make this all happen, at the point where we used to create the buttons. so say we have a button before called "show advanced features" that called a function drawButtons. Instead of that function drawing to our table, all we need for it to do now is set a viewstate property and post back so I just linked the show features button to a drawButtons.click event

        private void drawButtons_Click(object sender, EventArgs e)
        {
            ViewState["drawButtons"] = "true";
        }

     now when the user clicks this it will post back, the page_load will see the post back, see that there are more then 0 viewStates, see that this one is true, and then work through the code to add the buttons. This example isnt really pratical but it might help you understand. because my page was complicated i had to set more then just 1 view state, i had about 3, one saying what kind of button to add (save, edit, add), what table to add it to, and what event to tie it to. then in the postback using case and if statments i sorted it all out and got the events working.

    I hope that my rambeling isnt confussing.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, July 4, 2007 4:13 PM
  • User450306044 posted

    ImageButton ibSend = new ImageButton();

    ibSend.ImageUrl = "images/bt_send.gif";
    ibSend.ID = "ibSend";

    ibSend.Click += new ImageClickEventHandler(ibSend_Click);

     

    //Tip: after putting += just press tab twice visual studio will create the below.

     

       void ibSend_Click(object sender, ImageClickEventArgs e)
        {
           //blah blah blah
        }

    Thursday, February 19, 2009 4:27 AM