Problem:
I am loading one of several user controls based on a selected tab within RadTabstrip Control which is on the parent page. I've captured the Selected Tab and assigned it to a Session variable within the OnTabClick event to use in each User Control to determine if that particular control needs to be rendered.
The reason for this is because each User Control queries a database to render different charts and I don't want unneccesary processing occuring on every post back to the server. I'd like to add that each User Control has several Labels in their Markup that only gets the Text values assigned during runtime based on the content retrieved from the database.
When I load the main page, the selected tab variable is checked by each User Control and everything works fine from that scope. (The first tab at index 0 has no Charts)
Problem is when I select a Tab which has a User Control, the appropriate code to acquire the data from the database and build the chart works fine but the TEXT value of the Label controls in the Markup don't show up on the Page, although the TEXT values are being set in the Code-Behind at the same time the data is being retreived.
If I perform a Post Back of the same page, the TEXT values of the Label controls appear.
I believe this is because the 1st stages of the Page Life Cycle which include the rendering of the Markup aren't firing on the initial loading of the User Control, but get fired on subsequent Reloads or Refreshes of the Page.
Is there a way to work around this? I am figuring a call to the Render event after hitting the database would work but I may be way off base on my thoughts.
Can anybody provide some advice or a potential solution???
Thanks
I was never able to resolve the late binding issue which prevented the text of the labels from appearing until after a manual refresh of my page so I approached the issue from a different angle. I still retained the logic that only allowed the data of each User Control to get populated if their corresponding Tabs were selected by the user, but I moved the in-line code which was embedded in my Markup to my Code-Behind file.
I was not 100% certain as to the order that the mark-up vs. the code-behind got processed, so I researched and found that anything done declaratively in the aspx page is processed first, and the objects are created before being accessed or updated in the code behind.
So with this information I totally separated the two and was able to get the Text to render on the labels without any issue.
I still would haved liked to have known the appropriate way to force a page to call the Render event to simulate or mimick a manual Postback after the initial Page_Load, but going with the flow of the Page Cycle is the much easier and probably a more preferable way to do things.
One way to approach your problem is to consider use of the "Update Panel". It will allow you to render the entire page and then on an event only refresh the area of the update panel.
Generally I would love this feature for performance reasons but there is a catch. Some browsers (e.g. versions of Safari and Opera) do not render these correctly. Is your application a web application intended for general use by consumers? If so you may need to consider a full page refresh on the same page and pass the user data (unless Opera / other browsers have fixed this shortcoming - I have not tested in in 4 months).
Related
I have something like
protected void Page_Load(object sender, EventArgs e){
country.Text = "USA";
}
protected void Button_Click(object sender, EventArgs e){
Console.Write(country.Text);
}
and when the user clicks on the button, it always prints "USA", even if they wrote something else in the country TextBox, it means that Page_Load() gets fired each time a button (or any other event, I guess) is clicked.
I know how to fix this, by looking at this question, but why does that happen?
The web page is sitting on the client side web browser. When you click a button, the whole page is sent up to the server. Now you code behind can not only run, but modify controls, and does whatever you want. Once all that code is run, then the browser page is sent back down to the client.
I have often suggested that a FirstPage load event would have helped mountains here. However, over time, I think the page load having to fire each time is fine, and that the setup actually helps and promotes the fact that it runs every time. However, in desktop development - from VB6, .net, heck even delphi and C++ desktop forms? The page load even ONLY ever fires one time. So yes, it is surprise to many that web forms don't work this way. The bottom line is that page load fires every time, and the simple matter is a WHOLE NEW fresh page is sent up to the sever EVERY TIME. So, while there could have been two events, often quite a bit of page load code has to run in both cases. So then having two seperate events would cause just as much trouble.
So for code that runs first time (such as setting up the text box value)? Well, if you need that code to run each time (and you might!!!), then you place it outside of the if/then block that checks for the IsPostback. So for code to setup things such as defaults - yes, you need that code inside your IsPostBack = false block.
Web pages are what we call state-less. They are sitting on the users desktop. There is NO LIVE connection to the server. The user can close that web browser or turn off their computer. And when the user closes the browser - no information or talking is sent to the server. So you can have 2 or 2000 users typeing or editing in their brwoser - the web server does not care, see or even know that users are doing things. And the web server considers them NOT CONNECTED. They are just a web page - that page can be closed - the server does not even know the user closed the web site (there is no web page close event like desktop software). So the whole design of web pages are sate-less - and disconnneced. The web server does not know if that web page is still open, being used, or been closed. The ONLY time the web server can do ANYTHING is if you send the page back up to the server. At that point EVERYTHING in that web page starts over from scratch every post back (hence the term state-less). However, thankfully things like a text box have what is called a "view state" and they DO survive those round trips. If a control does not have a view state, then they also would lose their values on each post back. One VERY nice feature of webforms is most controls have the ability to keep their viewstate (that just means the value(s) of such controls can survive a round trip.
So when you click a button, then a whole page postback has to occur, since any code running behind would not be able to look at/ see / change the value of controls on the form. In fact, we often seen someone say run a ajax web method (in the same page) and then wonder why their code behind (in that web method) can't change controls. In fact you can write code to change controls, but it only changing the server side copy, and the copy sitting on the user's desktop is not changed. In fact, when they do (eventually) a post back, anything the code behind changed is lost.
So when you click on a button, the page load event will run FIRST and then your button code. This is how it works.
So 99% of the time, when I start typing and writing code in page load?
You do this: (say to load up a datagrid with a data table).
if IsPostBack = False then
GridView1.Datasource = myrst("SELECT * from tblhotels")
GridView1.Databind()
End if
So, you have to "assume" and "write" code that means the page load event fires every time. However, in above, we only want the first time setup code (to load up a gridview) to run one time - the first time the page loads. So now, you might have 5-6 buttons on the page, and the above code in the page load will not run since we check/test if this is a post back.
So the whole web page has to travel up to the server, else your code behind can't modify any controls or values on the web page. Once that code runs, then the page travels back down to the client side and is again just sitting on the users desktop. So clicking a button HAS to send the whole web page back to the server, else the values of controls on the web page could not be modified, and worse the results of that code would never be displayed back in the browser. So code behind can't JUST modify one control. it needs a whole copy fo the web page first, and then you can change a control (or several) and then the whole page makes the trip back to the browser. So you can't write code to JUST change one control without first having a WHOLE copy of the web page with everything. However, you can use what is called a update panel. This will allow you to run code that updates JUST part of the page. However, even in that case, the page post back event does run first - this is often called a partial page post back. So you can drop in a update panel, and have buttons and code in that update panel - they can only modify things inside of that update panel, but you note that the whole page does not replot or re-fresh. You can also hand code JavaScript ajax calls, and they can client side modify some controls (and even call routines server side). But you still have to assume that code behind can NOT see + use those controls until such time the web page travels up to the server. This applies even when using a up-date panel (the code behind can only modify controls in the update panel). Update panels are very nice in that you don't have to wire up and hand code a whole bunch of ajax and JavaScript to allow partial updates of the web page and not have to cause a full page post back. But as noted, even when using a up-date panel, the page load event does fire. So for the most part, you in general write the page load and setup code inside of that postback=false code block.
This is what the ASP.Net Button class tells us about the Button class:
By default, a Button control is a Submit button. A Submit button does
not have a command name (specified by the CommandName property)
associated with the button and simply posts the Web page back to the
server.You can provide an event handler for the Click event to
programmatically control the actions performed when the Submit button
is clicked.
Apologies if this is vague or too general, I know we are supposed to ask specific programming questions, but this is to try and understand how postbacks work in ASP.NET when something is rendered on page initially, and not touched on postback, yet still appears on screen after these postbacks.
Detail: I have an ASPX page - on initial page load it sets up all the labels and controls and a repeater with thumbnails in it.
I can follow the code through as it sets up all components, which will then be rendered.
On postback, if a value has been changes (status for example), the page makes updates to database, and then re initializes the screen (calls the init method with postback set to false), setting up everything again (I think the aim was to set up certain controls like radio buttons for the status), including the image repeater again (which I think is a waste of time).
I have tested skipping the code that sets up the image repeater etc. on a status update (postback), and the image repeater displays fine in the browser - however I am not sure why - ASP.NET is stateless, so on a postback, if the page does not render all the components on the page everytime how can they persist between postbacks?
I know there is a reason out there, just can't frame my question well enough in google to find it. Does the server send back and update which the browser merges with the existing displayed page? Leaving all unchanges components as is?
The reason I need to know this, is I have a screen with a lot of images on it, and I do not want to be setting them every time unless I have to.
This link - provided by Steve (thank you very much) - was what I was looking for goes into depth on ViewState - vaguely remember reading about that when I first stated doing .NET - have completely forgotten about it, but this explains it perfectly!
Understanding ASP.NET ViewState
https://msdn.microsoft.com/en-us/library/ms972976.aspx
Or a way to detect it is finsihed rendering?
Actually almost exactly this question
Gridview, is there an event, how would I determine that it has finished being rendered?
but he does not state exactly how he detected that everything had been drawn/resized.
EDIT: (Adding my comment from below to specify what i am trying to do)
I am trying to create a work around for static header for a gridview by basically dynamically adding another gridview above the one that actually has the data in it. I resorted to this after trying about 12 different suggestions/solutions with no real luck. What i have works pretty well except that the new header is rendered before the one with the data in it completes its re-sizing, I realize what i am trying might not even work since it might require another postback to re-render the new one after i find the sizes of the column headers but thought i might get around that with an update panel.
I realize this might not be the most elegant solution but honestly have yet to find any solutions to this problem that come even close to elegant or have even worked correctly with current browsers.
It renders at the client so the server doesn't know what is happening there.
You are probably looking for the DataBound event.
Otherwise, at the client, you can determine when the page has finished loading (the jquery ready function) and then call back to the server. But I can't imagine anything useful you could do. If you send more data to the client and it renders again, you could have an infinite loop.
Everything in an ASP.Net webpage is rendered at the same consecutively at the same stage of the lifecycle (see http://msdn.microsoft.com/en-us/library/ms178472.aspx), so the Gridview will be rendered between Gridview_PreRenderComplete and Gridview_Unload.
You page PreRender will fire, then the control PreRender, then the page will call the Gridview Render method (there is no event for this) then the control Unload will fire and then the page Unload will fire.
Other posters to this question are referring to the client side rendering whereas I am referring to the server side rendering process. Which is it that you are actually after and why please?
I am using WPF Page navigation in a c# windows based application. There are a series of pages that I am creating like this
Page TargetPage = new myPage01();
TargetFrame.Navigate(TargetPage);
The first-time page creation and navigation are working fine, and because I am passing by object the pages are kept alive for me to reference at a later point.
When the user hits the last page (all different views of the same data) and clicks the next button I want the UI to "loop" around to the first page. I am trying to figure out how I can redirect the frame to that first page. I do not want to rely on the built-in journal history within the GUI itself. How can I reference the first page previously created or for that matter any of the previously created pages by referring to it in the code. All the page navigation examples I have come accross are always creating the page as new or using the back or next to navigate to other pages.
Thanks
I do not want to rely on the built-in journal history within the GUI itself.
If you do not want to do that you need to keep track of everything yourself, which i would not recommend unless there is something wrong with the build-in functionality. You can probably find the first page to be the last item of the BackStack.
Here's a fun problem. The page in question is wizard like page. here's the scenario-
User clicks on a link button to get to step 2 of the wizard. (The post back can't be avoided. URL based navigation isn't an option.)
User clicks on a radio button/link button/any control that requires a postback for client-server interaction.
The page reloads as if nothing happens.
User repeats step 2. Things work fine.
What I do is this -
I have just one page for all steps of the wizard. Based on the step, the appropiate control is loaded into the page. This control is added to a placeholder control in the OnLoad event. Doing so in OnInit or OnPreRender doesn't work. This step of adding introduces the odd behaviour I've described above.
Any ideas?
Since you're adding controls to your page at runtime to get the wizard to appear on one page, I think this is a simple matter of rearranging some of your code.
Refer to this article at CodeProject - specifically the section that discusses viewstate and dynamic controls in the section called - "Walkthrough 6: Viewstate and Dynamic Controls".
Very simple, you have to re-add control on each postback, re-attach event handlers and give dynamically loaded control same Id.
The application uses a custom control framework. The issue is related to the framework. Had to redesign the approach.