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.
Related
I got a website where you must be logged in to access it, however, if the user lost the Session "loginID", the user should be kicked out immediately by a if(Session["LoginID"] == null) via MasterPage. But since im new to HTML/asp.net, Im not sure where I should actually have it, in Page_Load or Page_PreRender.
Does it even matter which one I have it in?
Using asp.net/c#
Thanks.
You can use Page_PreInIt event for your problem to check if session is live or ended
protected void Page_PreInIt(object sender,EventsArgs e)
{
if(Session["LoginID"] == null)
{
// redirect to login if session is null
Response.Redirect("Login.aspx");
}
}
Page Load:
The Page object calls the OnLoad method on the Page object, and then
recursively does the same for each child control until the page and
all controls are loaded. The Load event of individual controls occurs
after the Load event of the page
Page PreRender
Raised after the Page object has created all controls that are
required in order to render the page, including child controls of
composite controls. The Page object raises the PreRender event on the
Page object, and then recursively does the same for each child
control. The PreRender event of individual controls occurs after the
PreRender event of the page
Read More
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.
I've got aspx page which dynamically loads UserControl into a Panel object based on the input on a set of radio buttons. The UserControl successfully adds and displays properly to the Panel on postback and calls the Page_Load() event just fine in the UC but when I interact with the form in any way that would trigger an event, the event is not captured on the postback.
I've tried to add the event handling association in the Page_Load() which I know gets called as well as adding the association in the ASP.NET tag without any difference in result.
This is how I am adding the control (object names have been simplified):
private UserControl _control;
protected void RadioButtonGroup_CheckedChanged(object sender, EventArgs e)
{
RadioButton radioButton = (RadioButton)sender;
if (radioButton == RadioButton1Ctl)
{
_control = (UserControl1)LoadControl("~/Controls/UserControl1.ascx");
PanelCtl.Controls.Add(_control);
}
else if (radioButton == RadioButton2Ctl)
{
_control = (UserControl2)LoadControl("~/Controls/UserControl2.ascx");
PanelCtl.Controls.Add(_control);
}
}
As I said, the control gets successfully added by when I click any buttons or have any postback events which should be bound on the UC, the control gets removed from the page and events aren't fired.
Any help would be greatly appreciated.
This is happening because the controls are being added dynamically. I would suggest using the DynamicControlsPlaceHolder instead of a Panel. It will persist your controls for you when the page is posted back.
DynamicControlsPlaceHolder:
http://www.denisbauer.com/ASPNETControls/DynamicControlsPlaceholder.aspx
The other alternative is to recreate the controls at every postback, before the ViewState is reloaded. I would suggest using OnInit.
The DynamicControlsPlaceHolder takes all of the hard work away, so that might be the best option for you.
I have built an ascx control that is part of many different components of my application. There is a Previous and Next button on this control, which should be signaled to the parent aspx page. This is done by having the parent page add some Delegates for postbacks, such as OnPreviousClicked, OnNextClicked etc.
Everything in this app is 'ajaxified' with an updatepanel. Now I notice that my app breaks if I don't set the delegates on every single Page_Load call in the parent. In other words, if I don't ALWAYS set the delegates in the Page_Load of the parent aspx, then the ascx ends up with null delegates and an exception. Am I coding stuff correctly?
// inside the control
public event EventHandler OnPreviousClicked;
private void PreviousButton_OnClick(object sender, EventArgs e)
{
if(OnPreviousClicked != null) {
OnPreviousClicked(this, e); // or whatever args you want
}
}
// and inside the Page code-behind
private void Page_Load(...)
{
MyUserControl.OnPreviousClicked += new EventHandler(myHandler);
}
// OR inside the Page aspx, you also could just set the OnPreviousClicked property.
<xx:MyUserControl ID="MyUserControl1" runat="server" OnPreviousClicked="myHandler" />
See http://asp.net-tutorials.com/user-controls/events/.
If all you're doing is signaling the clicking of a button, I would have your ASCX control raise a simple event instead. That way each page can listen for the event if they need to and the controls can function regardless if anybody is listening.
First declare the events in your ASCX codebehind:
public event System.EventHandler NextSelected;
Then you create your button click events that raise the event.
protected void btnNextSelected_Click(object sender, EventArgs e)
{
if (EmployeeSelected != null)
{
NextSelected(this, new EventArgs());
}
}
Then in your parent ASP.Net pages you can add your ASCX control (we'll call it NavControl) and create methods that listen for these events.
NavControl.NextSelected += new EventHandler(NextPageRedirect);
protected void NextPageRedirect(object sender, EventArgs e)
{
Response.Redirect("~/ViewEmployee.aspx", false);
}
Note that with this you don't have to create the event handler or method and you can still use the nav control on your page. It should also eliminate the issues you are having with the delegates.
remember each postback has to restart your code. The event handlers don't get serialized to viewstate so you have to set them up again.
That is the expected behavior in asp.net.
The entire page life cycle occurs even when it is a partial postback (update panel). So in order for the events to fire, you will have to wire them up programmatically during page_load or declaratively in your markup (if those delegates you mentioned are events).
Basically, I have a drop down list and a dynamically added user control. The user control loads a grid view depending on the choice that was made in the drop down list. The drop down list is not part of the user control.
Now, the question is, how do i simulate (isControlPostback = false) every time the user changes the selection in the drop down list? It looks like ViewState remembers the control.
Inside my user control I have:
protected bool IsUserControlPostBack
{
get
{
return this.ViewState["IsUserControlPostBack"] != null;
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsUserControlPostBack)
{
ViewState.Add("IsUserControlPostBack", true);
//load stuff in the grid view and bind it
}
}
When the user changes the selection on the drop down list, i have a javascript confirm box, and the page posts back. So OnSelectedIndexChanged event for drop down list doesn't get triggered. I would like to remove to do something like this every time the selected index changes:
ViewState.Remove("IsUserControlPostBack");
You can make changes to the control in prerender event. When this event is fired all other actions are made.
Or you can do public property in user control and when setting required to value react on appropriately.
The ViewState you access in your user control is not the same one you access on the page. If you need your page to communicate with your user control, I suggest you add a public method on your user control for this purpose.
If, for some reason, you prefer
something similar to your ViewState
approach, you can try Context.Items.
Note that Context.Items is not
preserved between requests.
Add the control to the page sometime before OnLoad. E.g. OnInit. Between OnInit and OnLoad, the viewstate is loaded and postback events are run.
For anyone who is interested to know the answer:
I ended up implementing a public property inside user control and load the control inside the server drop down list SelectedIndexChanged event rather than OnInit. This eliminated the need for explicit Viewstate use.