Traditional way of initializing controls with the values from session state as below -
if (!IsPostBack)
{
if (Session["sessionId"] != null)
{
//initialize controls
}
}
Exhibits unexpected behavior when user control is wrapped inside update panel.
I need to populate usercontrol textBox values first time from session state. And subsequent loading of these controls values should be populated from viewState.
How do you handle this scenario. Do you think Page.IsAsync will be helpful for this ?
IsPostback property returns true even if postback fired from control, placed in an UpdatePanel. So it's ok to use IsPostBack property for control initializing on first page load.
By the way Page.IsAsync property serves for absolutely different purpose, not for detecting asynchronous postbacks. If you need to detect asynchronous postback from UpdatePanel, check ScriptManager.IsInAsyncPostBack property
Related
I have written a code in VB.NET in which there are around 300 asp controls and all of them are creating dynamically with more than 6 condition per control (like If control = dropdownlist then some code Elseif control = radiobuttonlist then some other code).
Now I want to write events for some controls but due to postback, when event is fired all of the controls are getting flushed.
When I set button1.onclientclick="return false" for button, the page stopped post back but the event also stopped working.
I have an option to save the values of controls in view state then recreating the controls and then refill the values to dynamic controls. This option will increase my line of execution.
Is there any other method though which I can prevent the page to post back on asp control event so that my asp control persists with entered values in it and also my event will work.
this is the Code1
this is the Code2
Create your dynamic controls OnPreInit Event of Page, Hope this solves your problem
override protected void OnPreInit(EventArgs e)
{
CreateDynamicControls();//Function which creates all dynamic controls
}
I have used JavaScript and Ajax to achieve my requirement.
I have called JS function for button's onclick and Textbox's onchange (like: btn1.Attribute.Add("onClick",JSFunction(); return false;) [return false is to prevent postback].
Then I used ajax post method to do my stuff on .vb page.
I had an interview a week ago and one of the questions was what the difference was between OnInit and Onload in ASP.NET? I had no clue and I don't find any simple answers on the net so can someone explain shortly and simple what the difference is between both? (What I found was that the difference was somehting in the lifecycle).
OnInit (the Init event) happens after all controls have been initialized, but before ViewState tracking is enabled. It's called bottom-up (the Init events for child controls are called before their parent's Init event).
Init is a good place to add dynamic controls to your page or user control (though it's not a requirement). If you can, then those controls will have their ViewState restored automatically during postbacks (see below). It's a risky place to set control properties, though, because they can be overwritten by incoming ViewState. Init is the right place to set ViewStateUserKey, which can help protect your site from one-click attacks. You would also call RegisterRequiresControlState() from there, if you're using control state.
Right after the Init event, each control enables ViewState tracking, so any changes to a control's properties after that will be reflected in ViewState.
The next events at the page level are InitComplete and PreLoad, neither of which is visible at the control level. During a postback, incoming ViewState is restored into controls between InitComplete and PreLoad.
Then comes the Load event, which happens for both controls and the page. Load is called first at the parent level, and then for any child controls. A master page behaves like a control on a page with regard to event ordering.
You need to read up on the ASP.NET page lifecycle.
OnInit happens earlier in the lifecycle - view state changes have not been done yet and tracking of it has not been turned on.
Page_Init is raised before Page_Load. Page_Init is a good place for code that you want executed before you process further such as attaching event handlers to the load event.
it is better not to access controls in this event because you aren't guaranteed they have been created.
The Page_Load is a good place to store code where you initialize values and any controls specific to the page because you know at this point the controls exist and are available.
You will place a lot more code in Page_Load than you will in Page_Init for the majority of your apps
Both these methods of Control class are invoked by ASP.NET. OnInit() method raises the Init event and OnLoad() method raises the Load event.
I have a user control that I am explicitly calling from an aspx page. In page_load of the aspx page I have the following:
myControl = (DynamicTable)Page.LoadControl("../inc/DynamicTable.ascx");
Then in my code where I want it to execute the control, I have this:
pnlESDDEnrolled.Controls.Add(myControl);
where pnlESDDEnrolled is the panel I am loading it into for display.
So, I execute the aspx page, it links off to the user control, populates the control, returns back to the aspx page and the page displays with the user control in the middle of it. All is well.
The problem comes in when updates are made on the user control. Keep in mind, that other data is updated on the page as well, and the update button resides on the page, not the control. Anyway, when the update button is pushed, the button_click event is fired on the page, but the updates that I made on the user control are lost. Since the page loaded the user control and then the usercontrol executed the page unload method, the page has no knowledge of the user control anymore. Thus, when the update button on the page is pushed, I guess I am not really sure what happens with the updated data on the user control. All I know is that it is lost. I have been working on this for a huge amount of time, any help would be much appreciated
You need to check for IsPostBack in your user control, too.
As your page loads, the Page's Page_Load event starts, then your UserControl's Page_Load will begin, execute, then its events, then controls returns to the page's Page_Load, then all of its events. Of course, if you are using Pre_Init on the page or overriding OnInit in your controls, those events execute before the Page_Load.
So, if you are dynamically creating items on your UserControl, check for IsPostBack and places those events an override OnInit function in the UserControl. Then add your programmatic reference to that UserControl in the Page_Init of the page.
I guess while you're talking about user control state these are realised as Properties in the code?
If so, then you're probably going to have to use Viewstate to persist the UserControl's state so that when the page comes back, the UserControl will be re-populated first with what it previously had when it was being rendered. This is as simple as changing any public state properties to use ViewState as the backer.
I'm not a great fan of viewstate, but sometimes it has to be used.
However there may be more at work here - as your instincts are telling you, this might also be a problem with the fact that this usercontrol is loaded dynamically.
In which case, it all depends at which part of the page lifecycle you're doing it. You need to get this control into the page's tree before render (pre-render might be possible), as it's at this point that that page 'captures' its controls collection for the purposes of maintaining state.
Try and move the insertion of this control into the page structure as early as you can in the lifecycle. The earlier the better - so Page_load would be fine.
Equally - it might be you're already doing this - in which case I'd need more information (perhaps a reproducable scenario) in order to help fix it.
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.
I have some code that modifies a value that several controls in other update panels are bound to. When this event handler fires, I'd like it to force the other update panels to refresh as well, so they can rebind.
Is this possible?
Edit:
To clarify, I have an update panel in one user control, the other update panels are in other user controls, so they can't see each other unless I were to expose some custom properties and use findControl etc etc...
Edit Again:
Here is what I came up with:
public void Update()
{
recursiveUpdate(this);
}
private void recursiveUpdate(Control control)
{
foreach (Control c in control.Controls)
{
if (c is UpdatePanel)
{
((UpdatePanel)c).Update();
}
if (c.HasControls())
{
recursiveUpdate(c);
}
}
}
I had 3 main user controls that were full of update panels, these controls were visible to the main page, so I added an Update method there that called Update on those three.
In my triggering control, I just cast this.Page into the currentpage and called Update.
Edit:
AARRGGGG!
While the update panels refresh, it does not call Page_Load within the subcontrols in them...What do I do now!
What about registering a PostBackTrigger (instead of an AsyncPostBackTrigger) that will refresh every panel when a specific event fires.
Or add the trigger that already refreshes some UpdatePanels to the other UpdatePanels as well.
You can set triggers on the events in the update panel you want updated or you can explicitly say updatepanel.update() in the code behind.
This is a good technique if you want to refresh updatepanel from client side Javascript.
Page.DataBind() kicks off a round of databind on all child controls. That'll cause Asp.Net to re-evaluate bind expressions on each control. If that's insufficient, you can add whatever logic you want to make sure gets kicked off to an OnDataBinding or OnDataBound override in your usercontrols. If you need to re-execute the Page_Load event, for example, you can simply call it in your overridden OnDataBound method.
instantuate both view panels to a third presenter class, Then let the presenter class control both views. for example:
You could just pass over what you need the 'middle class' to do its job for example, in your main you could have;
PresenterClass.AttachInterface(mIOrder);
PresenterClass.DoSomeCalulation();
PresenterClass.drawPanel(1);
PresenterClass.AttachInterface(mIOtherOrder);
PresenterClass.DoSomeCalulation();
PresenterClass.drawPanel(2);
each view will have its own controls. So many differant ways you could do this.. alternitivly you could use the middle class to instantuate both your panels then in each of your panels you could have 'get methods' to retrive the data for processing.