Dynamically add Button to Panel - c#

I am adding a RadButton dynamically to a Panel. So I am creating the button as so:
RadButton btnAwesome = new RadButton();
btnAwesome.AutoPostBack = true;
btnAwesome.Text = "Click me...";
btnAwesome.ID = "LinkButtonTest";
btnAwesome.Click += new System.EventHandler(lnkbtnEditRecord_Click);
and it it should call this method onclick:
protected void lnkbtnEditRecord_Click(object sender, EventArgs e)
{
salesEditPanel.Visible = true;
resultPanel.Visible = false;
zipPanel.Visible = false;
ddlPanel.Visible = false;
topPanel.Visible = false;
}
It adds the button the Panel but it doesn't add the onclick to it. Any idea what I am missing?
Thanks!

You will need to run that code to initialize the button on every postback, and you will need to ensure that it's run sufficiently early in the page's lifecycle. Which page event is that code in, and will it be run on each successive postback?

The issue here is due to how postbacks work - Each time a page is requested (postback or not), the control instances are created. Once the controls are created and other page properties set, the viewstate is parsed to set the control's properties. Then events are created and dispatched.
The important thing here is, this instance of "page" is not the same instance that you generated before - it's a new one and the ASP.NET webforms engine has set all the properties for you as if it were the same. But on this instance, you haven't created your btnAwesome, so there's nothing there to send a "click event" from or to!
In order to change this, you need to make sure that by the end of Page_Load, all of the controls you want to fire events have been created. So you must recreate btnAwesome and add it to the panel before returning from Page_Load if you want it to fire the click event.

Related

ASP.NET C# Issue Adding event handler to ImageButton CodeBehind

I'm having problems adding an event to an ImageButton. I have to create a set of buttons depending on a selected option from a DropDownList. The buttons are created successfully with Database data, but I'm can't attach the OnClick functionality.
The created buttons must share the same Handler.
protected void cmbServ_SelectedIndexChanged(object sender, EventArgs e) {
ServiceID = cmbServ.SelectedValue.ToString();
ServiceName = cmbServ.SelectedItem.ToString();
DataTable dtFirstTab = new DataTable();
dtFirstTab = mySQLConn.getTable(qryCarry); // LOAD DATA FROM DB
foreach (DataRow row in dtFirstTab.Rows) {
FTabBtn = "btn"+(Convert.ToInt32(row["SKU_Credito"])).ToString();
FTabIconURL = row["SKU_Icon"].ToString();
Panel dvFirstTab = new Panel();
dvFirstTab.CssClass = "col-xs-2";
ImageButton IB = new ImageButton();
IB.ID = FTabBtn;
IB.ImageUrl = FTabIconURL;
IB.Click += new ImageClickEventHandler(btnX_click); // <-- PROBLEM
dvFirstTab.Controls.Add(IB);
pnlIcons.Controls.Add(dvFirstTab); // pnlIcons exists in HTML
}
protected void btnX_click(object sender, ImageClickEventArgs e) {
string Obj = ((ImageButton)sender).ClientID;
Cantidad = Convert.ToInt32(Obj.Substring(3, (Obj.Length) - 3));
txtMonto.Text = "$" + Cantidad.ToString();
}
All the buttons appear correctly, but when I click on them they just fire a "submit" action, acting like there's no OnClick assigned.
No CodeBehid example:
If I add this line in HTML (I removed asp tags)
ImageButton ID="btn10" runat="server" ImageUrl="MontoLogo_10ST.png" OnClick="btnX_click"
It does work as intended.
Any ideas? Thanks a lot!
Creating controls dynamically in ASP.NET webforms usually seems easy at the beginning, but problems are very common when it comes to handling events. Even if you assign your event handler correctly, the event handler is not run in a postback until you re-create all the dynamic controls early in page lifecycle. This explains why the sample with the ImageButton on the ASPX works whereas the dynamically created buttons don't.
See this page for details on creating controls dynamically. The most important part is the warning that basically says: if you need to add dynamic controls, better don't.
Usually you can find a way to create all the necessary controls in markup, for instance using a Repeater control. The big advantage of the repeater is that you have control about the markup that is created.
The following sample outlines the necessary steps:
Place a repeater on your aspx-page. If pnlIcons serves no other purpose than being the container for the dynamically created buttons, substitute it by the repeater. Use the Header- and FooterTemplate properties to add the markup that surrounds the ImageButtons (e.g. the div for dvFirstTab).
Think about which data you need to assign to the image button. In your case, the fields "SKU_Credito" and "SKU_Icon" seem to be required.
Place the Image button in the ItemTemplate of the repeater and bind the properties "Id" and "ImageUrl" to the corresponding fields.
Add a Command event handler and bind the CommandArgument property to a value that helps you discern between the image buttons.
In the command event handler, you can use the CommandArgument to discover which button has been clicked. Add the appropriate code that handles the command.
In the SelectedIndexChanged event handler, read the data from the database and bind the repeater to the result. This creates the rows in the repeater with the ImageButtons.
Ok, I've found the reason. The event handling must be assigned in Page_Load event, so I moved everything inside a method and called it from Page_Load, calling it from "SelectedIndexChanged" doesn't work . It's working now.
Thanks!

How to prevent AutoPostBack from resetting my page?

I am building a page that includes some components that are static on the page (dropdowns, buttons, a table to hold them in), but one table cell is filled with variably generated CheckBoxes. When a button is pressed, the code for the page calculates what checkboxes to place and creates a new CheckBox object for each one needed and then adds it to an existing Div on the page.
I am trying to trigger some code to run when any of these are checked or unchecked, but checkBoxName.CheckedChanged += cbCheckedChanged wasn't working. I researched and found two suggestions: enabling viewstate and enabling autopostback.
checkBoxName.EnableViewState = true; seems to make no difference, nor did checkBoxName.ViewStateMode = ViewStateMode.Enabled; or any variations on that i tried. checkBoxName.AutoPostBack = true; did SOMETHING, but it's not allowing it to run the code I want. I think that's because it doesn't reach that point because of the next problem:
With AutoPostBack = true, whenever I check or uncheck a box, cbCheckedChangedis not being executed, and the entire page is reloading, resetting back to it's initial state, therefore removing the checkboxes completely from the table.
How can I fix these problems, or at least where might I start looking?
Edit:
This is where the checkboxes are created:
CheckBox cb = new CheckBox();
cb.Text = CBName;
cb.EnableViewState = true;
cb.ViewStateMode = ViewStateMode.Enabled;
cb.AutoPostBack = true;
cb.CheckedChanged += CBCheckedChanged;
and this is where CBCheckedChanged is:
private void CBCheckedChanged(object sender, EventArgs e)
{
\\Stuff
}
When I use breakpoints to step through it, it never reaches CBCheckedChanged. I have tried every possible combination of commenting out and leaving in the AutoPostBack, ViewStateMode, and EnableViewState lines.
Page_Load is currently empty, nothing runs until the user hits a button.
ViewState is by default enabled for server side controls. You don't have to tinker around with ViewState to solve your problem. ViewState is basically used to restore the state of a control after a postback happens. For example readding all entries to a ListBox control. This is why most control population code is within such a construct in the Page_Load method.
private void Page_Load()
{
if (!Page.IsPostBack)
{
// populate controls here
}
}
ViewState is a very misunderstood concept. There is a great article here that goes into it in detail. But as I said, for your problem ViewState is not a concern.
To solve your problem:
The problem in your case is that the triggered button is creating the CheckBox controls, but when the page is reloaded, because of the CheckedChanged event of these controls, the next page life cycle has no clue of the CheckBox controls that were placed on the page in the previous page life cycle. Dynamic controls need to be generated for every page life cycle!
So what I would do is create a method that:
creates the CheckBox controls and
sets AutoPostback = true for them and
sets the event handler for CheckedChanged
Let's call this method AddDynamicCheckBoxes(). Now you need to call this method in the Page_Load event of your Page when the button was already pressed and also in the event handler of the button's click event. You could do this like follows:
private void Page_Load()
{
if (ViewState["button_was_clicked"] != null)
{
AddDynamicCheckBoxes();
}
}
private void Button_OnClick()
{
AddDynamicCheckBoxes();
ViewState["button_was_clicked"] = true;
}

ASP User Control Event Fires After Containing Page's OnLoadComplete

I have a user control "UserApplianceControl" that I need to dynamically add to a asp page.
I am doing so with the following code:
User.aspx.cs
protected override void OnLoadComplete(EventArgs e)
{
base.OnLoadComplete(e);
A5Lib.User u;
UserServiceReference.UserServicesClient myProxy = new UserServiceReference.UserServicesClient();
u = myProxy.GetUser("user1");
if (listOfAppliances != null)
{
foreach (A5Lib.Appliance str in u.Appliances)
{
UserApplianceControl uac = (UserApplianceControl)LoadControl("UserApplianceControl.ascx");
uac.setAppliance(str);
Panel1.Controls.Add(uac);
}
}
}
In UserApplianceControl, I have several buttons. However, whenever I press a button, the user control's button handler is never called. In fact OnLoadComplete(above) gets called first, and so those controls populated on the last page load are recreated and I lose the old ones before I can handle the event.
Why isn't the event firing before OnLoadComplete?
You are recreating your controls too late in the page lifecyle.
A dynamically added control must be present (loaded) no later than onInit for any viewstate/postback functionality to work.
Move your code to the page's OnInit event. This will ensure that all the controls are rebuilt BEFORE viewstate is restored and the page does all it's button/event hooking up.

adding an event handler to a dynamically created checkbox (aspx, c#)

So my problem is that I want to add an event handler to a dynamically created CheckBox. I have already looked at other ways to do this, and decided that creating a dynamic table which contains my CheckBoxes is the best option for me. I have not added these CheckBoxes to the Control Tree because I need to manage the ViewState manually. Either way, my code works in every way except that my CheckBox's CheckChanged Event does not fire. I am adding this eventhandler to my CheckBox in my pageLoad event, however, any page event I try seems to give me the same results:
CheckBox chbxLv1 = new CheckBox();
chbxLv1.ID = "DymanicallyCreatedIDForIdentification";
chbxLv1.AutoPostBack = true;
chbxLv1.CheckedChanged += new EventHandler(this.checkChanged);
/* Way lower in my code */
protected void checkChanged(object sender, EventArgs e)
{
//Some code goes here which never seems to execute... grrr
}
I thought that this may be a problem with the ViewState at first and did quite a bit of research on that. I'm now thinking I am doing something dumb with adding an event handler. I'm not sure why this event never fires, but I'm a little new at adding events to a control. Do I need a delegate here?
--Roman
In order for dynamically loaded controls to be handled properly during the ASP.NET Page Lifecycle, they need to be added to the page during OnInit (or prior to LoadViewState, really) otherwise their state information will not be maintained and you can, in fact, corrupt the viewstate depending on how/where things are added in the page's control graph.

Asp.NET Server Control Postback

I have a Control I want to create. Here's a simple example of what I was to accomplish.
I want the control to contain a button.
Button b = new Button();
b.Text = "Test";
b.Click += new EventHandler(b_Click);
this.Controls.Add(b);
Now, the control renders fine, the button shows up on the page. The heart of the problem I'm having is that the b_Click Event Handler is never triggered.
protected void b_Click(object sender, EventArgs e)
{
throw new NotImplementedException();
}
Any help here would be much appreciated. I don't want to use a User Control here for purely selfish reasons and would like to totally encapsulate this in a single DLL.
Thanks In Advance.
EDIT**
namespace ClassLibrary1
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:WebCustomControl1 runat=server></{0}:WebCustomControl1>")]
public class WebCustomControl1 : WebControl
{
protected override void CreateChildControls()
{
Button b = new Button();
b.ID = "button";
b.Text = "Click Me";
b.Click += new EventHandler(b_Click);
this.Controls.Add(b);
base.CreateChildControls();
}
protected void b_Click(object sender, EventArgs e)
{
this.Controls.Add(new LiteralControl("<p>Click!</p>"));
}
}
}
So from the comments I've tried this. The simplest of exampes, still no go. Is there something I'm fundamentally missing?
public class WebCustomControl1 : WebControl
needed to be
public class WebCustomControl1 : WebControl, INamingContainer
that's it. that's all that was needed to make this postback issue work.
Override the CreateChildControls method and create/add the button (and register the handler) in that method.
Using OnInit/OnLoad to create controls like this is incorrect and will lead to inconsistent behavior (such as what you're experiencing).
Edit: You might also try setting button.ID so that it's the same on every postback, it's possible the raised event isn't seeing it for that reason.
Please show the definition of your control class.
Does your control inherit from Control, WebControl, or CompositeControl. Try inheriting from CompositeControl and see if that helps.
So your button renders to the page correctly and causes a postback when the user clicks it, but the OnClick code never runs?
Remember, whenever you do a postback you're working with a brand new instance of your page class. Part of the postback process is running whatever event was triggered by the user. For this to happen, the asp.net processor needs to know about the event at a specific point in the page lifecycle. At this point, your button must already be on the page with the event handler registered. If this doesn't happen, your event won't fire. Try moving your button creation up earlier in the page lifecycle.
This may be the case of assigning the handlers well after the event is raised.
My common practice when dealing with controls are:
Use Control.Init event to initialize everything (default text, handlers, size, composition, etc.) and also initialize the child controls.
Use Control.Load event to handle any data binding operation (based on the properties/fields set during the Init event).
Check the identifier of the button control before the postback and after the postback. If it's not the same, it won't work.
You can overwrite the identifier yourself if needed.

Categories

Resources