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.
Related
I have a user control that I dynamically add to a Panel. I also have a couple of other functionality in the aspx page like search which is inside an update panel that causes the page to post back. From what I have read so far is that dynamic control needs to be bound on each page load. This works fine but the issue is that the user control takes a bit of time (like 3s) and thus all request operations takes longer because the user control is being bound every time.
If I load the user control inside the Page.IsPostBack condition and load it only on page load then user control is visible on post back but all the associated events in the user control is not fires.
So, Is there a way in which I can store the user control data in a session and then bind it if I know that the data is not going to change and hence reducing the 3s delay to load the user control.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
LoadUserControl(); // Only loaded on page load.Faster, but user control
//functionalities break on post back. Maybe
// because it is not loaded again.
}
//LoadUserControl(); // User control loads fine. But even a totally unrelated
// post back causes the already loaded User Control to load
// again. 3s delay :(
}
The method used to load the user control is
private void LoadUserControl()
{
var control = LoadControl("A Dynamic ascx page");
control.ID = "contentControl";
panel1.Controls.Clear(); //panel1 is the placeholder in aspx page
panel1.Controls.Add(control);
Session["LoadedControls"] = control;
}
So I tried to save the loaded control in session and add in to the placeholder panel as such
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
LoadUserControl(); // Only loaded on page load.Faster, but user control
//functionalities break on post back. Maybe
// because it is not loaded again.
}
if ((Control)Session["LoadedControls"] != null)
{
panel1.Controls.Clear();
panel1.Controls.Add((Control)Session["LoadedControls"]);
}
}
this does not work as expected either. I do not get any of the data present in the user control.
The user control has 2 RadGrid and 2 RadHTMLChart. I did not want to add it since this is already a huge post. the data for the controls in user controls is also being stored in session for binding again. But I am unable to find a way to add the user control dynamically with the bound data.
I am trying to modify a control on a page to reduce session dependence. I currently do not have access to the page itself, only the control which primarily consists of a DataGrid. I am trying to retrieve the DataGrid information on postback so I can manipulate the data and rebind the grid.
The issue is that the page is calling a databind on the control before I can retrieve the data. (actually it is calling the databind on the tab control where my control is located.) This call is happening on the OnLoad event of the page, before the OnLoad of the control is called. I saw that the is a PreLoad event that occurs after the viewstate is loaded but before the OnLoad is called. However I am having issues accessing this event from my control. Is there anyway I can access this event so I can retrieve the data before the page overwrites it?
Add the following code to your control instead of the OnLoad. (from here)
protected override void OnInit(System.EventArgs e)
{
// this assigns Page_PreLoad as the event handler
// for the PreLoad event of the Control's Page property
this.Page.PreLoad += Page_PreLoad;
base.OnInit(e);
}
private void Page_PreLoad(object sender, System.EventArgs e)
{
// do something here
}
This might help: MSDN - ASP.NET Page Life Cycle Overview
The image 1/3 of the way down sums it up.
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 understand the order the events occur with page life cycle but it is not helping with my situation. I have a checkboxlist that is populated by a directory filled with forms. When I check a box next to the name of the form I would like it to dynamically create a wizard step and insert the form.
Order of events:
OnInit:
GatherForms() - Checks directory and loads all form names into checkbox
LoadForms() - Checks "Selected" Session and loads forms that were collected
CheckBoxList:SelectedIndexChanged #AutoPost = true#
PopulateForms() - Loops through the checkboxs and adds them to session state
When the user clicks the checkbox it does a postback and hits the OnInit which pulls from the session. The problem is that PopulateForms() was not ran yet so it populated nothing even though it is checked. If I click another item it will postback and appear. I cannot seem to be able to pull any kind of useful information from the checkbox before the refresh which means I cannot see the forms appear immediately. I have also tried looping the checkbox but unfortunately viewstate hasnt posted yet. sigh.
Any suggestions?
Thanks!
P.S: I cannot use Request.Form[] because I have to get all the selected items out of the checkbox. maybe i can but i cannot find a way :/
This is a common problem I wrestle with as I get better at ASP.NET.
With dynamic controls you have the problem of them not actually existing during OnInit.
What you can do is create all of the controls the user may see during OnInit, and hide the elements the user won't see in code. The page will load, all possible controls will be instantiated (in code - don't worry this appearing in your HTML and bloating it), then the event handler will fire, and then you can deal with setting the visibility of your wizard.
For example:
public void OnInit(object sender, EventArgs e)
{
GatherForms();
CreateWizardForm(); // creates a wizard and adds controls it will need
}
private void Checkbox_Checked(object sender, EventArgs e)
{
var checkBox = (CheckBox)sender;
// append checkBox.SelectedValue to session state object of checkboxes
}
protected override void OnPreRender(object sender, EventArgs e)
{
if (/* Session checkboxes contain values */)
{
this.WizardForm.Visible = true;
this.CheckboxList.Visible = false;
}
}
This works provided you know ahead of time which controls will be in the wizard form. You can change the values of those controls in the OnPreRender event, toggle their visibility, etc, but you can't go and add new controls (e.g. Controls.Add(new Button())) - that has to be done in the OnInit event.
Only add your dynamic controls in OnInit. Don't do any population/processing until PageLoad. You will retain your values this way.
A classic pitfall with dynamic controls.
Honestly the best solution is to just wield the Request values array to look for the information you need and ignore the lifecycle stuff for this particular situation.
In OnInit(), the posted values are there, they just haven't been dealt with by ViewState yet. So you can just do if (Request["myCheckBoxName"] == xxx) to deal with individual checkboxes, or if you can use Request["__EVENTTARGET"] to get the name of the control that caused the postback.
See my old answer here for a more thorough discussion of the issue.
I have a rather complex page. The ASPX page loads a user control which in turn loads a child User control.
Parent Control
protected override void OnInit(EventArgs e)
{
//Loads child control
}
In the child user control, I use custom control that inherits from System.Web.UI.HtmlControls.HtmlSelect
ASCX:
<cust:CustDropDownList id="ctlDdl" runat="server"/>
ASCX.CS
protected void Page_Load(object sender, EventArgs e)
{
//Binds CtlDdl here
}
When the user clicks on the Save button, the controls get user controls get dynamically reloaded, but Iose the value the user has selected in the dropdown. I run into the chicken and egg problem here.
I think I need to bind the ctlDdl only on if its not a postback, but that results in the dropdown not getting populated.
If I bind it everytime, then i lose user's selection
EDIT:
Can someone respond to my comment to Jonathan's answer? Thanks
With custom controls, you have to manage the state. There is a sort of bubble-up effect where the state is passed along. If you don't deal with it, you don't get state.
This link will get you started: Server Control Custom State Management
Look for
Protected Overrides Sub LoadViewState( _
ByVal savedState As Object)
Dim p As Pair = TryCast(savedState, Pair)
If p IsNot Nothing Then
MyBase.LoadViewState(p.First)
CType(Author, IStateManager).LoadViewState(p.Second)
Return
End If
MyBase.LoadViewState(savedState)
End Sub
at Custom Property State Management Example
Just override the OnInit method in the user control and load the custom control from that method. ASP.NET sets viewstate tracking after OnInit and before PageLoad. Therefore the defaults that are being set when you load the control are being treated as changes by the viewstate engine and are being reset on the postback.
See this article on viewstate for a detailed explanation:
http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/truly-understanding-viewstate.aspx