Solved

C# Dynamically Created Control Event Handler not working

Posted on 2010-09-08
16
808 Views
Last Modified: 2012-05-10
I have a dynamically created button control with an EventHandler in C#.  The control is generated, but when I click the button it does not fire the event handler.  Can anyone give me some suggestions for this?
TableRow r2 = new TableRow();

        TableCell c2 = new TableCell();

        Button btnSubmit = new Button();

        btnSubmit.ID = "btnSubmit";

        btnSubmit.Text = "Submit";

        //btnSubmit.CausesValidation = true;

        btnSubmit.Click += new EventHandler(btnSubmit_Click);

        c2.Controls.Add(btnSubmit);



        r2.Cells.Add(c2);

        Table1.Rows.Add(r2);



protected void btnSubmit_Click(object sender, EventArgs e)

    {

        lblResponse.Text = "Button Clicked";

        lblResponse.Visible = true;



    }

Open in new window

0
Comment
Question by:Dukster131
  • 7
  • 6
  • 3
16 Comments
 
LVL 3

Expert Comment

by:aledev
Comment Utility
0
 
LVL 3

Expert Comment

by:aledev
Comment Utility
This explains how to handle event for dinamically created objects

http://weblogs.asp.net/ksamaschke/archive/2003/02/18/2595.aspx
0
 
LVL 1

Author Comment

by:Dukster131
Comment Utility
this code is generating a web application form.  I did not see anything in the above two articles that would explain why this eventHandler is not working.
0
 
LVL 3

Expert Comment

by:aledev
Comment Utility
this is part of the second link

What, if there was a chance to react on the button's click? Even if this reaction was not handled by the button's eventhandler? Look at this:

' Registering a hidden field in the Page
Page.RegisterHiddenField(Me.UniqueID & _
   "_buttonClicked", "")

' Defining the Button
Dim objButton As New Button
objButton.Text = "Click me!"

' Here's the trick... :)
objButton.Attributes.Add("onClick", _
   "document.forms[0]." & Me.UniqueID & _
   "_buttonClicked.value='" & _
   objButton.UniqueID & "';document.forms[0].submit();")

' Adding the button to the page
Page.Controls.Add(objButton)

What was done here? Really simple: We added a JavaScript to the button which sets a value in the hidden field. On PostBack we're able to track this hidden field and detect, wheter the button was clicked or not:

' Use this snippet on PostBack
If Page.IsPostBack Then
   If Request.Item(Me.UniqueID & _
      "_buttonClicked").Length > 0 Then
      Response.Write("Button " & _
         Request.Item(Me.UniqueID & _
            "_buttonClicked") & _
            " was clicked!")
   End If
End If
0
 
LVL 1

Author Comment

by:Dukster131
Comment Utility
Wow.  That seems really convoluted to just get the EventHandler for the Click event.  Also I need to know how to do this for a radio list that is generated to determine which button was clicked and make a textbox visible or invisible on each row - which could be up to 53 rows of dynamically generated radio lists.  I don't think the solution above is going to work for that.  I'm just wondering why the following does not work.

btnSubmit.Click += new EventHandler(btnSubmit_Click);
 and then do whatever I need to do in the btnSumbit_Click event.
0
 
LVL 33

Accepted Solution

by:
Todd Gerbert earned 500 total points
Comment Utility
You absolutely can add event handlers as you suggested.  The code you have posted in your question works fine, you must have something else going on.
This is my test, which works as expected...just be aware you need to create the controls on every page load, i.e. if you're running the code you posted inside an if (!IsPostBack) block it won't work.

<%@ Page Language="C#" %>



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">



<script runat="server">

	protected void Page_Load(object sender, EventArgs e)

	{

		TableRow r2 = new TableRow();

		TableCell c2 = new TableCell();

		Button btnSubmit = new Button();

		btnSubmit.ID = "btnSubmit";

		btnSubmit.Text = "Submit";

		//btnSubmit.CausesValidation = true;

		btnSubmit.Click += new EventHandler(btnSubmit_Click);

		c2.Controls.Add(btnSubmit);



		r2.Cells.Add(c2);

		Table1.Rows.Add(r2);

	}



	protected void btnSubmit_Click(object sender, EventArgs e)

	{

		Response.Write("Dynamic Button Clicked");

	}

</script>



<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

    <title></title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

    <asp:Table ID="Table1" runat="server">

	</asp:Table>

    </div>

    </form>

</body>

</html>

Open in new window

0
 
LVL 33

Assisted Solution

by:Todd Gerbert
Todd Gerbert earned 500 total points
Comment Utility
Here's a video describing more of what you might want...http://www.asp.net/ajax/videos/how-to-dynamically-add-controls-to-a-web-page
0
 
LVL 1

Author Comment

by:Dukster131
Comment Utility
Yes, that is what I needed to know.  I did have it in a !IsPostBack.  Once I took it out of there it worked.  I will look at the video you have suggested - just wish it was in c#.  This submit button was out of loop that I am running on generating the rows.  However, within the loop I have some radioLists that are being generated for each row with a textbox for comments.  I didn't know if you might have an idea on adding the EventHandler for the RadioLists.  I'll put what I have below.
//Add a Radio Button List



                RadioButtonList rdbtnList = new RadioButtonList();

                rdbtnList.ID = "rdList" + count;

                

                

                rdbtnList.Items.Add(new ListItem("Green", "Green"));

                rdbtnList.Items.Add(new ListItem("Amber", "Amber"));

                rdbtnList.Items.Add(new ListItem("Red", "Red"));

                rdbtnList.SelectedIndex = 0;



                rdbtnList.RepeatDirection = RepeatDirection.Horizontal;

                c.Controls.Add(rdbtnList);

                r.Cells.Add(c);

Open in new window

0
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 
LVL 33

Assisted Solution

by:Todd Gerbert
Todd Gerbert earned 500 total points
Comment Utility
I think there was C# example code next to that video - you should have a look, because it's not too far off from what you're doing.
As for the event handler - I think that I would probably use one function, then in that event handler you can cast the "sender" parameter to a Button, e.g., and check the Button's ID property to determine which one was clicked.
0
 
LVL 1

Author Comment

by:Dukster131
Comment Utility
I'm not sure I'm following you on casting to Button.  Here is what I came up with maybe you can point me in the right direction:

rdbtnList.SelectedIndexChanged += new EventHandler(this.rdbtnList_SelectedIndexChanged);

So I created the Event Handler.  I'm just not sure how to capture which radio button was selected and the value of it.

protected void rdbtnList_SelectedIndexChanged(object sender, EventArgs e)
    {
       
            lblResponse.Text = "Button Clicked ";
            lblResponse.Visible = true;
       

    }
0
 
LVL 33

Assisted Solution

by:Todd Gerbert
Todd Gerbert earned 500 total points
Comment Utility
Sorry, I didn't really make myself clear - I was just using a Button for the sake of an example, but you can do it with any control.
<%@ Page Language="C#" %>



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">



<script runat="server">

	

	protected void Page_Load(object sender, EventArgs e)

	{

		int counter = 0;

		foreach (List<string> data in GetRowsFromDatabase())

		{

			RadioButtonList rbl = new RadioButtonList();

			rbl.ID = "RadioButtonList" + counter.ToString();

			foreach (string value in data)

				rbl.Items.Add(value);

			rbl.SelectedIndexChanged += RadioButtonList_SelectedIndexChanged;

			listsPanel.Controls.Add(rbl);

			listsPanel.Controls.Add(new LiteralControl("<hr />"));



			counter++;

		}

	}



	private void RadioButtonList_SelectedIndexChanged(object sender, EventArgs e)

	{

		// All RadioButtonLists are using this same event handler,

		// so to know which one cast "sender" to a "RadioButtonList"

		// ("sender" is the control that caused the event to fire)

		RadioButtonList list = sender as RadioButtonList;

		

		if (list != null)

		{

			changedListIdLabel.Text = list.ID;

			selectedValueLabel.Text = list.SelectedValue;

		}

	}

	

	private List<List<string>> GetRowsFromDatabase()

	{

		// This method simulates retrieval of data from database

		List<List<string>> rows = new List<List<string>>();



		List<string> cars = new List<string>();

		cars.Add("Honda");

		cars.Add("Ford");

		cars.Add("BMW");

		rows.Add(cars);



		List<string> planes = new List<string>();

		planes.Add("Boeing");

		planes.Add("Cessna");

		planes.Add("Airbus");

		rows.Add(planes);



		return rows;

	}

</script>



<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

    <title></title>

</head>

<body>

    <form id="form1" runat="server">

		<div runat="server" id="listsPanel"></div><br />

		Changed list: <asp:Label ID="changedListIdLabel" runat="server"></asp:Label><br />

		Selected value: <asp:Label ID="selectedValueLabel" runat="server"></asp:Label><br />

		<asp:Button ID="updateSelectionButton" runat="server" Text="Update Selection" />

    </form>

</body>

</html>

Open in new window

0
 
LVL 1

Author Comment

by:Dukster131
Comment Utility
Ok.  My problem is not generating the different radiobuttonlists.  My problem is finding out which radio button has been selected for each row.  there are three buttons with values of Green Amber and Red.  I can generate the number of rows I need - one for each computer.  So if there are 50 computers and I have all the radio lists generated and I want to get the values for each one, how do I loop through those to get the values when they click on a submit button.  Also I would like to make a textbox visible when they choose Red or Amber for any computer on the line for that computer.  I already have the textboxes being generated as invisible so I just need them to appear when Amber or Green is chosen for that computer.
0
 
LVL 33

Assisted Solution

by:Todd Gerbert
Todd Gerbert earned 500 total points
Comment Utility
Same basic concept.  By assigning the RadioButtonLists an ID that ends with a unique number, you can associate that radio button list with a particular row in the table in the event handler by casting "sender" to a RadioButtonList and checking it's ID property.
 
Here's a rough idea that needs some refinement and error handling:

<%@ Page Language="C#" %>



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">



<script runat="server">

	

	protected void Page_Load(object sender, EventArgs e)

	{

		string[] computers = {"Pinky", "Brain", "Jerry"};

		for(int i =0; i < computers.Length;i++)

		{

			TableRow newRow = new TableRow();



			TableCell computerCell = new TableCell();

			Label computerLabel = new Label();

			computerLabel.Font.Bold = true;

			computerLabel.Text = computers[i];

			computerLabel.ID = "ComputerLabel" + i.ToString();

			computerCell.Controls.Add(computerLabel);

			computerCell.BorderStyle = BorderStyle.Solid;

			newRow.Cells.Add(computerCell);



			TableCell amberRedYellowCell = new TableCell();

			RadioButtonList list = new RadioButtonList();

			list.ID = "AmberRedYellow" + i.ToString();

			list.Items.Add("Amber");

			list.Items.Add("Red");

			list.Items.Add("Yellow");

			list.SelectedIndexChanged += RadioButtonList_SelectedIndexChanged;

			list.AutoPostBack = true;

			amberRedYellowCell.Controls.Add(list);

			amberRedYellowCell.BorderStyle = BorderStyle.Solid;

			newRow.Cells.Add(amberRedYellowCell);



			TableCell textBoxCell = new TableCell();

			TextBox textBox = new TextBox();

			textBox.ID = "TextBox" + i.ToString();

			textBox.Visible = false;

			textBoxCell.Controls.Add(textBox);

			textBoxCell.BorderStyle = BorderStyle.Solid;

			newRow.Cells.Add(textBoxCell);



			ComputersTable.Rows.Add(newRow);

		}

	}



	private void RadioButtonList_SelectedIndexChanged(object sender, EventArgs e)

	{

		// All RadioButtonLists are using this same event handler,

		// so to know which one cast "sender" to a "RadioButtonList"

		// ("sender" is the control that caused the event to fire)

		RadioButtonList list = sender as RadioButtonList;

		

		if (list != null)

		{

			// Get the row number from the end of the list's ID

			string rownum = list.ID.Substring(14);

			

			// Use the row number to get the associated text box

			TextBox tb = FindControl("TextBox" + rownum) as TextBox;



			// Show or hide the text box as appropriate

			if (list.SelectedValue == "Amber" || list.SelectedValue == "Red")

				tb.Visible = true;

			else

				tb.Visible = false;

		}

	}



	private void ShowResultsButton_Click(object sender, EventArgs e)

	{

		foreach (TableRow row in ComputersTable.Rows)

		{

			string computerName = ((Label)row.Cells[0].Controls[0]).Text;

			string selectedValue = ((RadioButtonList)row.Cells[1].Controls[0]).SelectedValue;

			string textBoxContents = ((TextBox)row.Cells[2].Controls[0]).Text;



			ResultsDiv.Controls.Add(new LiteralControl(

				String.Format("{0}: {1}, &quot;{2}&quot;<br />", computerName, selectedValue, textBoxContents)));

		}

	}

</script>



<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

    <title></title>

</head>

<body>

    <form id="form1" runat="server">

		<asp:Table ID="ComputersTable" runat="server" BorderStyle="Solid"></asp:Table><br />

		<asp:Button ID="ShowResultsButton" runat="server" Text="Show Results" OnClick="ShowResultsButton_Click" />

		<hr />

		<div runat="server" id="ResultsDiv">

		</div>

    </form>

</body>

</html>

Open in new window

0
 
LVL 1

Author Comment

by:Dukster131
Comment Utility
Ok.  I'm getting close.  I'm not finding the Textbox though.  Here is what I have

 //Add a TextBox
                TextBox txtReason = new TextBox();
                txtReason.ID = "Reason" + j.ToString();
                txtReason.Columns = 50;
                txtReason.TextMode = TextBoxMode.MultiLine;
                txtReason.Rows = 3;
                txtReason.Visible = false;
                             
                c.Controls.Add(txtReason);
                r.Cells.Add(c);

Then on the Selected Index Changed event it always gives me a null value for tb below.

 protected void rdbtnList_SelectedIndexChanged(object sender, EventArgs e)
    {
       
         
        RadioButtonList list = sender as RadioButtonList;
        if (list != null)
        {
            // Get the row number from the end of the list's ID
            string rownum = list.ID.Substring(6);

            // Use the row number to get the associated text box
            TextBox tb = FindControl("Reason" + rownum) as TextBox;

            // Show or hide the text box as appropriate
            if (tb != null)
            {
                if (list.SelectedValue == "Amber" || list.SelectedValue == "Red")
                    tb.Visible = true;
                else
                    tb.Visible = false;
            }

        }
       

    }


0
 
LVL 33

Assisted Solution

by:Todd Gerbert
Todd Gerbert earned 500 total points
Comment Utility
Either the control can't be found, or whatever control was found couldn't be converted to a TextBox.  Put a breakpoint in rdbtnList_SelectedIndexChanged - what is rownum equal to, and is there really a text box on the page with an ID of "Reason" + rownum?  It's kinda hard for me to say with just those snippets - I can see you're setting the ID of the text box to "Reason" plus whatever j is, but I don't know what j actually is.  I also don't know what you're setting the ID of the RadioButtonLists to - if the ID of the RadioButtonList doesn't always end with the same number the TextBox ID ends with then this approach doesn't work.
0
 
LVL 1

Author Comment

by:Dukster131
Comment Utility
Yeah, I have all of the controls with the same counter so if it works for one it should work for all of them.  If I view source code it is showing a Reason1 etc.  for the textboxes.  I remembered something I had learned before and tried this and it seemed to work with the following code.

 protected void rdbtnList_SelectedIndexChanged(object sender, EventArgs e)
    {
       
         
        RadioButtonList list = sender as RadioButtonList;
        if (list != null)
        {
            // Get the row number from the end of the list's ID
            string rownum = list.ID.Substring(6);

            // Use the row number to get the associated text box
            string strTextBox = "Reason" + rownum;
            string strReason = "lblReason" + rownum;
            TextBox tb = (TextBox)list.Parent.Parent.FindControl(strTextBox) as TextBox;
            Label lblReason = (Label)list.Parent.Parent.FindControl(strReason) as Label;
            // Show or hide the text box as appropriate
            if (tb != null)
            {
                if (list.SelectedValue == "Amber" || list.SelectedValue == "Red")
                {
                    tb.Visible = true;
                    lblReason.Visible = true;
                }
                else
                {
                    tb.Visible = false;
                    lblReason.Visible = false;
                }
            }

        }
            }

Thanks for all the help I think I can figure the rest out.  
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

This article introduced a TextBox that supports transparent background.   Introduction TextBox is the most widely used control component in GUI design. Most GUI controls do not support transparent background and more or less do not have the…
Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…

728 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now