I have several instances of user controls on a page. They are also nested in each other. Since these controls are created dynamically, I am having trouble maintaining their state. I decided to save the state manually to a persistent medium (possibly Session).
On the click event on a button on the host page, I want to write functionality to save the state of the controls BEFORE the postback happens (Once there is a postback, the controls are recreated and I lose the state).
If I put this logic in the button event handler, since this is executed AFTER the postback, I dont have the information anymore.
Which method should I override?
Try creating your button in the Page Init instead of on load.
Not really answering you question, but I'm curious as to why the layout of your buttons is getting reset. Are you doing something via javascript?
How are you creating your buttons. in the page_load? are you checking when its a postback?
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
// load all buttons
LoadButtons();
}
}
It sounds like you are re-creating the controls on postback and so they lose their state. You should make use of Page.IsPostBack to prevent this. Also check that the page allows Viewstate.
Actually you want to be loading your dynamic controls in the LoadViewState method override. Don't try to maintain state yourself; it is a waste of time. You just have to put your code in the right place.
See My previous comments on this
Related
I have a set of programmatically added user controls on the page (they are created and added during the Init event of the main page). Each of these control programmatically add buttons during his own Init event.
(So it's "two levels" of dynamically created controls. Don't know if it matters.)
But I need to access the viewstate while creating those buttons (I use the viewstate to remember user data).
protected void Page_Init(object sender, EventArgs e)
{
// I need my ViewState right now !
Button myButton = new Button();
myButton.Text = "Click me";
myButton.Command += new CommandEventHandler(myCommandHandler);
myButton.CommandName = "Delete";
myButton.ID = "myButtonID";
myPlaceholder.Controls.Add(myButton);
}
I understood that the viewstate isn't available during the Init event. But buttons don't fire their events (OnClick, etc.) if they are created after the Init.
How to create dynamic controls and access the viewstate at the same time ?
I don't think you can. Not ideal but I would put the user data in the Session in this instance. Dynamic controls are difficult to work with and I think this is one of the trade offs. ViewState loads after Page_Init - this forum post confirms
Another option might be to store the information in your own hidden fields. These will become available in the Request.Form collection during postback and will be available. Of course if you make them runat="server" (which you will probably have to) the framework will append all the naming container ids to the name so you will have to be a bit clever when digging them out. It's going to get a bit hacky though so I would be tempted to stick to the Session
Someone else might know different of course.
I see some people are using Page_Load and Page_PreRender in same aspx page. Can I exactly know why do we need to invoke both the methods in same asp.net page?
Please see the code below,
protected void Page_Load(object sender, EventArgs e)
{
try
{
dprPager.ButtonClickPager += new EventHandler(dprPager_ButtonClickPager);
if (!Page.IsPostBack)
{
InitPager();
}
}
catch (Exception ex)
{
}
}
protected void Page_PreRender(object sender, EventArgs e)
{
erMsg.Visible = !string.IsNullOrEmpty(lblError.Text);
}
The major difference between Page_Load and Page_PreRender is that in the Page_Load method not all of your page controls are completely initialized (loaded), because individual controls Load() methods has not been called yet. This means that tree is not ready for rendering yet. In Page_PreRender you guaranteed that all page controls are loaded and ready for rendering. Technically Page_PreRender is your last chance to tweak the page before it turns into HTML stream.
It depends on your requirements.
Page Load : Perform actions common to all requests, such as setting up a database query. At this point, server controls in the tree are created and initialized, the state is restored, and form controls reflect client-side data. See Handling Inherited Events.
Prerender :Perform any updates before the output is rendered. Any changes made to the state of the control in the prerender phase can be saved, while changes made in the rendering phase are lost. See Handling Inherited Events.
Reference: Control Execution Lifecycle MSDN
Try to read about
ASP.NET Page Life Cycle Overview ASP.NET
Control Execution Lifecycle
Regards
Page_Load happens after ViewState and PostData is sent into all of your server side controls by ASP.NET controls being created on the page. Page_Init is the event fired prior to ViewState and PostData being reinstated. Page_Load is where you typically do any page wide initilization. Page_PreRender is the last event you have a chance to handle prior to the page's state being rendered into HTML. Page_Load
is the more typical event to work with.
Well a big requirement to implement PreRender as opposed to Load is the need to work with the controls on the page. On Page_Load, the controls are not rendered, and therefore cannot be referenced.
Processing the ASP.NET web-form takes place in stages. At each state various events are raised. If you are interested to plug your code into the processing flow (on server side) then you have to handle appropriate page event.
The main point of the differences as pointed out #BizApps is that Load event happens right after the ViewState is populated while PreRender event happens later, right before Rendering phase, and after all individual children controls' action event handlers are already executing.
Therefore, any modifications done by the controls' actions event handler should be updated in the control hierarchy during PreRender as it happens after.
I am calling my user control in a web page dynamically.
For the first time when I click the button on user control, the event is not firing. When I click the same for a second time, the events are firing..
Can anyone help me?
Sounds like the hookup to the button OnClick event is not occurring on every page load, which is required.
Can you guarantee that the hookup is being performed when you add the control and after a poastback to the page? I always put my event hooks in the Page_Init or Page_Load event handlers and outside of any Postback check. Try putting a breakpoint on the Handler hook up and see if the breakpoint gets "hit" twice.
An event hookup for a button would look similar to:
protected void Page_Load(object sender, EventArgs e)
{
btnSearch.Click += new EventHandler(btnSearch_Click); // breakpoint on this line
}
The client id of the control is derived from the ID of all containing controls that are marked with the INamingContainer interface. So, make sure that ALL controls in the hierarchy have a fixed ID.
For example if you have a Button control inside a Repeater, the ID of the button and the repeater are concatenated to make the client ID for the button. So both the repeater and the button should have the same ID across postbacks.
You can compare the HTML for the first request with the HTML of the second request to quickly determine if this is the problem.
Assign an ID for your dynamically created control -- otherwise no events will be fired.
Are you waiting for the download of full page before pressing the button?
The events are javascript functions hidden by ASP.Net in the page, that maybe not present at the time of your clicking.
I have an ASP.NET web form which I am adding a variable number User Controls to. I have two problems:
The User Controls are added to a PlaceHolder on the form in the first PageLoad event (I only add them when "(!this.IsPostback)", but then when the form is posted back, the controls are gone. Is this normal? Since other controls on the form keep their state, I would expect these dynamically added ones to stay on the form as well. Do I have to add them for every postback?
I also have a button and an event handler for the button click event, but this event handler is never called when I click on the button. Is there something special I have to do to catch events on dynamically added controls?
Yes, you need to add them in every postback.
Yes... the control needs to be in the control hierarchy before asp.net dispatches the event (i.e. create the dynamic controls as early in the page lifecycle as possible).
1) You should add the controls on the Pre-init (Page life cycle)
2) You have to attach the event handler to the event of the created button.(events might occur much later in the page life cycle than the same events for controls created declaratively)
To achieve this, add your controls at page init instead of page load. (re-add at postback)
You'll need to know the id of the buttons added to bind them to the event.
I ran into a similar problem. I had a page that displayed a collection of custom web controls. My solution was to add an additional invisible web control so that when I clicked a button to add another control that I would just use the invisible one. Then on post back my load function would add another invisible control to the collection.
I figured out yesterday that you can actually make your app work like normal by loading the control tree right after the loadviewstateevent is fired. if you override the loadviewstate event, call mybase.loadviewstate and then put your own code to regenerate the controls right after it, the values for those controls will be available on page load. In one of my apps I use a viewstate field to hold the ID or the array info that can be used to recreate those controls.
Protected Overrides Sub LoadViewState(ByVal savedState As Object)
MyBase.LoadViewState(savedState)
If IsPostBack Then
CreateMyControls()
End If
End Sub
I ran into the exact same problem and struggled through like 5-6 hours.
I'm posting this maybe someone like me could get help.
1) You should initialize your controls at Page.PreInit event. (In my case I had to add my controls to a place holder so I extended PreInit to load those controls before but you don't need to do that. It depends on your scenario.)
2) You should bind those exact methods to your controls after you initialize them in your Page.PreInit event.
Here is my sample code:
protected override void OnPreInit(EventArgs e)
{
// Loading controls...
this.PrepareChildControlsDuringPreInit();
// Getting ddl container from session and creating them...
if (GetDDLSession().Count != 0)
{
foreach (DropDownList ddl in GetDDLSession())
{
ddl.SelectedIndexChanged += SelectedIndexChanged;
phDropDowns.Controls.Add(ddl);
}
}
base.OnPreInit(e);
}
public static void PrepareChildControlsDuringPreInit(this Page page)
{
// Walk up the master page chain and tickle the getter on each one
MasterPage master = page.Master;
while (master != null) master = master.Master;
}
I have a user control that is pretty basic. It contains several TextBox controls, a few DropDownList controls, a save Button and a cancel Button. I would like to use this control in two different modes. The first mode is in the normal postback mode to do the save and cancel actions. The second mode would use AJAX to do the save and cancel actions.
Is it possible to wrap the contents of the control in an UpdatePanel and then be able to turn on/off whether or not the UpdatePanel does AJAX or PostBack for the control events? Or would I be better served by just creating two new controls (1 with UpdatePanel, 1 without) to house the one old control?
Have a look at the Refreshing UpdatePanel Content section here: UpdatePanel Class.
But what I would do, personally, is just create the UserControl without the UpdatePanel, and then enclose it in one when you need to. Less confusing.
The easiest way to just 'turn off' your UpdatePanel is to set EnablePartialRendering to false in the ScriptManager. I'm not sure that this is the best solution. I would recommend adding your controls to an update panel in your codebehind Page_Load event handler based on a boolean flag.
void Page_Load() {
if(IsAjaxy) {
upAnUpdatePanel.Controls.Add(tbSomeTextBox);
}
else {
this.Controls.Add(tbSomeTextBox);
}
Something along those lines should work just fine.