I am trying to develop a page.
that has a button and a placeholeder.
on the click of the button a user control is added to the placeholder.
on each click of button that many user controls should be added to the placeholder.
i am trying to store placeholder in viewstate on preinit event but while retrieving placeholder from viewstate in load event viewstate remains null.
below is my code:
protected void PreInit(object sender, EventArgs e)
{
this.OnPreInit(e);
if (!Page.IsPostBack)
{
ViewState["c"] = PlaceHolder1;
}
else { PlaceHolder1 = (PlaceHolder)ViewState["c"]; }
}
protected void Page_Load(object sender, EventArgs e)
{
if(IsPostBack)
{ PlaceHolder1= (PlaceHolder)ViewState["c"]; }
}
public void addDepartmentBtn_Click(object sender, EventArgs e)
{
// User Control Code
c1 = LoadControl("~/AddDepartment.ascx");
PlaceHolder1.Controls.Add(c1);
}
If viewstate is not suitable in this scenarion then what is the alternative way to achieve this ?
You have to re-add controls to your place holder on each post back.
Your attempt to ViewState is barking up the wrong tree-- ViewState is for something entirely different and even if you wanted to, you can only store serializable things into ViewState.
If you are trying to add controls to the page dynamically, that must be done in Init on each postback. This means that you must use a data structure (something persisted in ViewState will do) as a list of dynamically-created controls- NOT the controls themselves, but a hash of strings to use as IDs is a common method.
Each time the user does something to add a control to the page, add a key to the list. In the Page Init, you must then read the list and use it to recreate and add the dynamic controls back to the page collection or they will not appear on the page.
This is not going to work. ASP.NET server controls are too complex a thing to be stored in a ViewState. What server controls do, by ASP.NET design, is store their data (state, property values, etc) in Page's ViewState.
What you can do is store in ViewState the number of AddDepartment user controls that have been created and added to the placeholder. This can be done in PreRender. Then on postback, you read this number from the ViewState and create and add to placeholder that many AddDepartment controls.
Related
May I know if there is any way to invoke a method from the child page(.aspx) after the page load of the user control is finished?
Right now I have an issue of being unable to retrieve the value from the child page because the variables from the user control has not been assigned the value yet.
To put it simply
FROM MY .ASPX FILE
Page_Load(object sender, EventArgs e)
{
x = getValueFromUserControl();
}
FROM MY USER CONTROL
Page_Load(object sender, EventArgs e)
{
int x = getvalueFromDatabase();
}
getValueFromuserControl()
{
return x;
}
Since the ASP.NET Life Cycle goes from the child page(.aspx) page_load -> user control page_load, I am unable to retrieve the value of x.
That said, ideally I would not like to put the function in the child page and call it from the user control as the user control is being used in other pages.
In short, I would like to invoke a method from my .aspx page after the page_load in my user control ends, Thank you!
Get the value at a later page event:
protected override void OnLoadComplete(EventArgs e) {
x = getValueFromUserControl();
}
Unless, of course, there is a specific reason why you must get the value on Page_Load. There are other, probably more appropriate ways to handle this, but without knowing what x is and what you need to do with it, it is hard to give any other advice. For example, maybe the UserControl should fire an event that is handled by the page.
Inside a ListView Control's <ItemTemplate> I'm using a LinkButton.
When the List populates it has a set of LinkButtons. The link button text's are generated from a column in the records retrieved using a data source.
When I click on a LinkButton, I need it's text to be captured into either a hidden field or view state during the post back, so that it will be displayed in a Label or TextBox when page post back happens.
But it does not happen on first page post back. Instead, I have to click on the LinkButton twice for two post backs for the value to be displayed in Label/TextBox.
How can I get it done in the first post back ?
I have tried the same without the ListView, using just a LinkButton as below, and get the same outcome.
protected void LinkButton_Click(object sender, EventArgs e)
{
LinkButton selectedButton = (LinkButton)sender;
HiddenField1.Value = selectedButton.Text;
ViewState["LinkButtonText"] = selectedButton.Text;
}
protected void Page_Load(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(HiddenField1.Value))
{
Label1.Text = HiddenField1.Value;
}
TextBox1.Text = HiddenField1.Value;
if (ViewState["LinkButtonText"] != null)
{
if (!string.IsNullOrEmpty(ViewState["LinkButtonText"].ToString()))
{
ViewStateTextBox.Text = ViewState["LinkButtonText"].ToString();
}
}
}
Well, It happens since the sequence of the server side method execution. The page load before hand, then the control click methods, in that order. Instead of updating hidden field like that now using a client side JavaScript function OnClientClick of the LinkButton control, which updates the hidden field.
In short, you use it everytime you need to execute something ONLY on first load.
The classic usage of Page.IsPostBack is data binding / control initialization.
if(!Page.IsPostBack)
{
//Control Initialization
//Databinding
}
Things that are persisted on ViewState and ControlState don't need to be recreated on every postback so you check for this condition in order to avoid executing unnecessary code.
Another classic usage is getting and processing Querystring parameters. You don't need to do that on postback.
This code a have written for an asp.net website, v2005
System.Web.UI.WebControls.TextBox txtEFName = new System.Web.UI.WebControls.TextBox();
phFname.Controls.Add(txtEFName);
placeHolder1.Controls.Add(TextBox1);
This code when executed, always shows the value of the textbox "" even if I enter some string.
Please help.
Dynamic controls need to be re-created each time the page loads. So you need to have that code execute during the Page_Init event. Note: You need to assign a unique ID for this control that stays the same each time the page loads.
Why all this?
Because the control is not contained in the markup (the .aspx file), you need to add it again every time the page loads. So how does it retain its value? The value will be stored in the ViewState, and as long as the control has the same ID it will be repopulated with the correct value.
To keep things running smoothly, let's put the code for adding the control in a separate function.
Private void AddMyControl()
{
System.Web.UI.WebControls.TextBox txtEFName = new System.Web.UI.WebControls.TextBox();
txtEFName.ID = something unique;
phFname.Controls.Add(txtEFName);
}
So we can call it from both the click handler and the Page_Init handler, but we only need to call it in the Page_Init if we have already clicked. So let's store that as a flag inside a Session variable (you can also store it in the ViewState if you like, but let's keep it that way for now). So our click handler will now look something like this:
void ButtonSomething_Click(Object Sender, EventArgs e)
{
AddMyControl();
Session["MyControlFlag"] == true;
}
Now we need our Page_Init handler:
Public void Page_Init(Object Sender, EventArgs e)
{
if(Session["MyControlFlag"]!=null && (bool)Session["MyControlFlag"])
AddMyControl();
}
Im trying to load a usercontrol dynamically on a aspx page however it works but i get postback issues?? I have a image button on usercontrol which I want to show a image however when i do click on button the page refreshes and does not show image?. I have a placeholder on aspx page and backend code i have this :
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Control uc = Page.LoadControl("~/UserControls/Mycontrol.ascx");
placeholder1.Controls.Add(uc);
}
}
Do i need to do something in page_preinit or page_init ??
You should always reload the user control on the Page_init on each post back.
Dynamic controls added to the page must be added on every postback, not just the first one. Remove the !IsPostBack condition. Secondly, they have to be added during init or preinit, because that way, viewstate will be captured and restored properly (ASP.NET restores viewstate between init and load events).
Give the control an ID and also load the control in Page_init
uc.ID = "your id";
I am dynamically generating controls, and sometimes I want to create a control and have it ignore the viewstate. For example, sometimes the user has clicked a button indicating they want a different form loaded, so the control tree I generate on postback is different from the original control tree. This is fine, except when I call Controls.Add then it tries to load the viewstate form the old controls into the new controls if the control tree structure is similar, and I want them to instead ignore that viewstate(and also ignore the postback values for input controls as well).
Can I do something like set the IDs of the controls or something that would allow me to conditionally prevent them from getting the viewstate/postback data of the previous request?
Edit: If I let the user of the control load the form on demand in postback handler, the postback data is not applied when I call Controls.Add(this really seems like a flaw in ASP.NET, because I would think if you're going to apply viewstate data "after the fact" through Controls.Add, it'd seem you would then apply the postback data automatically as well after the viewstate data is loaded). The real problem I run up against is my control is very dynamic, but the user of my control can't really tell it what to do until their postback handler fires, because one of the things a user can do is select different forms to be loaded via some link buttons. So it's not until the postback handler runs that they know what the uesr requested, and thus can ask my control to load a certain form. So I have to ask them to do convaluted things like saved the formID that identifies the last form to a session variable, and in OnInit they tell my form what the old formID was via a property. My control then loads the form in OnLoad so that it can consume the viewstate and postback data, and later in the programmer's postback handler, they can choose to clear the form and load a different one if they want.
Edit2: FYI Generating IDs for each control unique to the form works great, so I thought I could eliminate the pointless loading of the old form until the programmer requests a form be loaded in his postback handler. But as I mentioned above, what I found was that loading the form after postback data handling has occurred means that data is lost. Whereas viewstate gets loaded via Contorls.Add, playing catch up in the page lifecycle, it seems postback data does not! So it seems I am defeated at every turn.
You're going to avoid problems if you play along with the control lifetime. Basically, whenever you have a control that renders, it's best to ensure that control is recreated on the next postback, even if you aren't going to need it anymore. The first goal of a postback should be to restore the previous state -- only THEN do you make changes to it.
I described it best in this answer:
Wrong state in Server Controls with same ID's when dynamically adding UserControl to UpdatePanel
Giving the controls different ID's would certainly prevent ViewState from being loaded, that would be one way.
You may also be able to manipulate the ViewStateMode property of your controls by setting it to "Disabled". I'm not sure if this prevents it from loading (it definitely prevents them from saving viewstate), but you could try it.
Have you tried just calling controls.clear prior to adding in the new ones?
UPDATE
I'm starting to believe that you are generating the controls at the wrong point in the page lifecycle. What is your flow?
You must be generating dynamic controls on postback in pageload:
protected void Page_Load(object sender, EventArgs e)
{
--Generate Dynamic Controls--
}
You need to do it like:
protected override void OnInitComplete(EventArgs e)
{
base.OnInitComplete(e);
}
protected void OnInit()
{
--Generate Dynamic Controls--
}
protected void Page_Load(object sender, EventArgs e)
{
}