C# Why does OnItemDataBound fire before Page_Load? - c#

I have a question about C# repeater. I have default width setting, and it will change base on some conditions in the Page_Load, I want change to be pass to my Image on OnItemDataBound. However, it seems that the OnItemDataBound is firing off before Page_Load because I changed the width to 700 in Page_Load, but when the image is loaded, it is always showing 380 instead. If OnItemDataBound is not the correct function to use, which function should I call so that I can change the image width after the Page_Load (where the custom width is set) is called? I tried OnPreLoad, OnLoad, and none of them worked.
protected int width = 380;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
width = 700;
}
}
protected void Test_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
RepeaterItem item = e.Item;
if ((item.ItemType == ListItemType.Item) || (item.ItemType == ListItemType.AlternatingItem))
{
Image Image = (Image)e.Item.FindControl("Image");
Image.ImageUrl = Utilities.generateImage();
Image.Width = width;
}
}

Databinding is done on PrerenderComplete event, which is fired on page lifecycle before PageLoad. For more info check https://msdn.microsoft.com/en-us/library/ms178472.aspx#lifecycle_events to see lifecycle events and their order.

If you declare the datasource in markup, it can render everything much earlier since you are not doing a manual databind. This can occur previous to Page_Load.
Try overloading an earlier event, such as OnLoad or OnPreLoad. Both of these occur prior to Page_Load.
If you are explicitly performing databinding and doing it in another event that occurs prior to Page_Load, then you'll have to ensure that the repeater is rebound if you want to change things. Once you call databind, it binds. If you need to change something either do it before or rebind.

You can use Page_Init for this. It fires before ItemDataBound:
protected void Page_Init(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// load
}
}
See also:
https://learn.microsoft.com/en-us/previous-versions/aspnet/ms178472(v=vs.100)

Related

linkbuttons postback before executing click event code?

I am trying to add a basic switch to my site in order to switch between static and responsive layouts.
I have two linkbuttons at the bottom of my page:
<div id="toggleView">
<asp:linkbutton ID="lbtnMobile" runat="server" Visible="false">Switch to Mobile site</asp:linkbutton>
<asp:linkbutton ID="lbtnFull" runat="server" >Switch to Full site</asp:linkbutton>
</div>
They both have a very similar OnClick event.
protected void lbtnFull_Click(object sender, EventArgs e)
{
c.ViewChange = true;
Session["Customer"] = c;
}
protected void lbtnMobile_Click(object sender, EventArgs e)
{
c.ViewChange = false;
Session["Customer"] = c;
}
The events should set a boolean in a class file (User.vb) between true or false and then save the session, on postback the Page_Load event is supposed to read this boolean and use it to adjust the Viewport meta tag:
protected void Page_Load(object sender, System.EventArgs e)
{
//Other Stuff in here, irrelevant to current question
HtmlMeta view = new HtmlMeta();
view.Name = "viewport";
if (c.ViewChange = false)
{
view.Content = "width=device-width, initial-scale=1";
lbtnFull.Visible = true;
lbtnMobile.Visible = false;
}
else
{
view.Content = "width=1040px, initial-scale=1";
lbtnFull.Visible = false;
lbtnMobile.Visible = true;
}
MetaPlaceHolder.Controls.Add(view);
}
However, when I click on the "Switch to Full Site" linkbutton, the page will postback but nothing will have changed. Does the postback get triggered too early somehow?
The page load event will happen BEFORE your click event. Reference this here.
This means your check for the ViewChange will happen before you set it in the OnClick handler.
You should change
if (c.ViewChange = false)
to
if (c.ViewChange == false)
for something to happen. But I think it won't be what you expect. Because page_load is executed before click event. You may move some code from page_load to click event handlers.
When ever you postback the Page_Load always get called. So, the code mentioned inside Page_Load would always get executed.
protected void Page_Load(object sender, System.EventArgs e)
{
... All your mentioned code will be executed.
}
Therefore, you won't find any change in your HTML page currently viewed in a browser because at postback initial content also got executed. You need to wrap your content inside !IsPostBack to make it work properly.
Thus, modify you code in following way.
protected void Page_Load(object sender, System.EventArgs e)
{
if(!IsPostback)
{
... All your mentioned code will be executed during normal load.
}
}
Also, you need to add some extra code in LinkButton click event i.e. what to show and what to hide.
Firstly your implementation in the Page_Load isn't very clear.
Nevertheless this is what I recommend, from what I've understod:
As the page load will get executed before the post-back event like the buton or link click, you need persist the value of the class object
Make a protected property of type of your class (where you store/manage the ViewChange atribute)
The property should internally (in the get & set), hold/persist the value in session/viewstate (similar to what you've written)
The setting and reading should only be by referring the property directly (and not how you've done the click-event)
On clicking of the button and post setting the new value, you will have to redirect to the same page, as only then the Page_Load event will get the new boolean value that you've just changed in the click-event; (Page_Load occurs befoer the any other post-back event)
An alternative to the fresh redirection is that, you could make a function that has the view changing logic (as depicted in your Page_Load code), and this function should be called on your button/link click event (post boolean value change) and also in the Page_Load event, but within the "!IsPostBack" block
Hope this helps you.

Dynamically Added DropDownlists Are Not Firing SelectedIndexChanged Event [duplicate]

This question already has an answer here:
Event won't fire to dynamically added control
(1 answer)
Closed 2 years ago.
I saw lots of thing about this topic but i can't fin a solution.
I add many dropdown list with one event but they are not firing SelectedIndexChanged evet.
Here is drplist creator code:
foreach (var row in cmdSelectCats.ExecuteReader())
{
var id = row["ProductCategoryID"].ToString();
var dropDownStatus = new DropDownList {ID = "DrpStatus-" + id};
dropDownStatus.Items.Add(new ListItem("Aktif", "1"));
dropDownStatus.Items.Add(new ListItem("Pasif", "2"));
dropDownStatus.AutoPostBack = true;
dropDownStatus.SelectedIndexChanged += Status_SelectedIndexChanged;
var tableCell = new TableCell();
tableCell.Controls.Add(dropDownStatus);
dropDownStatus.SelectedValue = row["ProductCategoryStatusID"].ToString();
tableRow.Cells.Add(tableCell);
TblCatList.Rows.Add(tableRow);
}
And ofcourse my Event:
public void Status_SelectedIndexChanged(object sender, EventArgs e)
{
//DO SOMETHING
}
What am i missing?
This is a common issue and it's related to the page life cycle:
Take a look at the following questions:
Click events on Array of buttons
Button array disappears after click event
Dynamically create an ImageButton
Now the basic steps to remember when creating dynamic controls are:
Dynamic controls should be created in the PreInit event when you are not working with a master page, if you are, then create the controls in the Init event
Avoid setting properties that can be changed in each post in these events because when the view state is applied (in a post event) the properties will be overridden
Dynamic controls must be created every time the page is posted, avoid this if(!this.IsPostBack) this.CreatemyDynamicControls();
When you create the controls in the PreInit or Init events, their states will be automatically set in a post event, which means in the LoadComplete event your controls will contain their state back even when you create them again in each post and even when you did not explicitly set their state. Note this behavior is different when you are dealing with controls created at design time, in that case, the event where the state has been set is the Load event
Event subscription should occur before the PageLoadComplete or they will not be raised
Consider the following description from MSDN
If controls are created dynamically at run time or declaratively within templates of data-bound controls, their events are initially not synchronized with those of other controls on the page. For example, for a control that is added at run time, the Init and Load events might occur much later in the page life cycle than the same events for controls created declaratively. Therefore, from the time that they are instantiated, dynamically added controls and controls in templates raise their events one after the other until they have caught up to the event during which it was added to the Controls collection.
The above is not so clear to me, but I have found the following. The following TextBox's are created at design time
protected void Page_PreInit(object sender, EventArgs e)
{
this.txtDesignTextBox1.Text = "From PreInit";
this.txtDesignTextBox1.Text += DateTime.Now.ToString();
}
protected void Page_Init(object sender, EventArgs e)
{
this.txtDesignTextBox2.Text = "From Init";
this.txtDesignTextBox2.Text += DateTime.Now.ToString();
}
protected void Page_Load(object sender, EventArgs e)
{
this.txtDesignTextBox3.Text = "From Load";
this.txtDesignTextBox3.Text += DateTime.Now.ToString();
}
At first sight you might think that in every post all the textboxes are updated with the current date, but this is not the case, since they were created at design time they follow strictly the ASP.Net page life-cycle which means, their state is overriden after the PreInit and Init events, only the txtDesignTextBox3 is updated in every post because its Text property is updated after the view state has been set (in the Load event).
But with dynamic controls the behavior is different, remember the MSDN description:
for a control that is added at run time, the Init and Load events might occur much later in the page life cycle
Consider the following:
protected void Page_PreInit(object sender, EventArgs e)
{
var textBox = new TextBox { Text = "From PreInit", Width = new Unit("100%") };
textBox.Text += DateTime.Now.ToString();
this.myPlaceHolder.Controls.Add(textBox);
}
protected void Page_Init(object sender, EventArgs e)
{
var textBox = new TextBox { Text = "From Init", Width = new Unit("100%") };
textBox.Text += DateTime.Now.ToString();
this.myPlaceHolder.Controls.Add(textBox);
}
protected void Page_Load(object sender, EventArgs e)
{
var textBox = new TextBox { Text = "From Load", Width = new Unit("100%") };
textBox.Text += DateTime.Now.ToString();
this.myPlaceHolder.Controls.Add(textBox);
}
In this case, the controls behave slightly different, in this case, in each post, the controls are never updated not even the controls created in the Load event
The reason is their life-cycle events occurs much later in the page-life cycle which means their state is overridden even after the Load event
To solve this, you can use the LoadComplete event, in this event you can change the state of dynamic controls:
protected void Page_LoadComplete(object sender, EventArgs e)
{
var textBox = new TextBox { Text = "From LoadComplete", Width = new Unit("100%") };
textBox.Text += DateTime.Now.ToString();
this.myPlaceHolder.Controls.Add(textBox);
}
In this case, the state will be updated in each post.
However, take in consideration that you should subscribe to dynamic controls events, before the LoadComplete event or they will not be raised.
... I know I hate this kind of behavior, that's why I love MVC
As a quick reference for controls created at design time: Notice how the LoadViewState method is called after the PreInit and Init events but before the Load event. The Load event is considered stable because in this event you can access the view state of your controls. Also notice that the RaisePostBackEvent method represent the control event that caused the post back, this can be, the SelectedIndexChanged, Click, etc this event is handled after the Load event
For a complete detailed specification read the MSDN Page Life-Cycle documentation
I have usually seen this caused by a page lifecycle problem. If the control is only created when an event is fired, then when your index changed event fires the control doesn't exist to bind it to on the postback.
Example:
MyEvent fires. Drop-down created. Event Handler specified.
Index Changed event triggered. Page reloads. Drop-down not found, cannot fire.
You have to ensure the drop-down is created before .NET attemps to handle the event.
You are missing:
1- Override SaveViewState
2- Override LoadViewState
I provide a sample code for this question. I test it. It's work.
ASPX:
<form id="form1" runat="server">
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
<div id="myDiv" runat="server">
</div>
<asp:Label ID="lblDescription" runat="server"></asp:Label>
</form>
Code Behind:
public partial class Default : System.Web.UI.Page
{
private List<string> values = new List<string>();
protected void Page_Load(object sender, EventArgs e)
{
}
protected override object SaveViewState()
{
object baseState = base.SaveViewState();
object[] allStates = new object[2];
allStates[0] = baseState;
allStates[1] = values;
return allStates;
}
protected override void LoadViewState(object savedState)
{
object[] myState = (object[])savedState;
if (myState[0] != null)
base.LoadViewState(myState[0]);
if (myState[1] != null)
{
values = (List<string>)myState[1];
MyRender();
}
}
protected void Button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
DropDownList ddl = new DropDownList();
ddl.ID = "ClientID" + i;
ddl.Items.Add("Item 1");
ddl.Items.Add("Item 2");
ddl.AutoPostBack = true;
values.Add(ddl.SelectedValue);
myDiv.Controls.Add(ddl);
}
}
private void MyRender()
{
for (int i = 0; i < values.Count; i++)
{
DropDownList ddl = new DropDownList();
ddl.ID = "ClientID" + i;
ddl.Items.Add("Item 1");
ddl.Items.Add("Item 2");
ddl.AutoPostBack = true;
ddl.SelectedIndexChanged += new EventHandler(ddl_SelectedIndexChanged);
myDiv.Controls.Add(ddl);
}
}
void ddl_SelectedIndexChanged(object sender, EventArgs e)
{
lblDescription.Text = ((DropDownList)sender).ID + ": Selected Index Changed";
}
}

Button Submit calls Onload first!

I have a problem with a webform.
My Goal: Intially when a page is loading, it has to load every textbox empty. After filling the info and click submit, it has to get submitted(UpdatePaymentInfo())
Problem: Here, When the user fills the info and clicks Submit,it calls onload function even before the submit button and makes all text box empty.
Here is the code:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
string QueryStringupdatecreditcard1 = Request.QueryString.ToString();
if (String.Equals(QueryStringupdatecreditcard1, "tabID=B"))
{
divTitle.Visible = false;
trmain.Visible = false;
tdOrderSummary.Visible = false;
trCCandBilling.Visible = true;
trtest2.Visible = false;
divUpdatecreditcard.Visible = true;
trusecompaddress.Visible = false;
txtFirstName.Text = "";
txtLastName.Text = "";
txtAddress1.Text = "";
txtAddress2.Text = "";
txtCity.Text = "";
txtZip.Text = "";
txtCardNo.Text = "";
txtVccNumber.Text = "";
trAmountCharged.Visible = false;
}
}
protected void imgbtnSubmit_Click(object sender, ImageClickEventArgs e)
{
try
{
UpdatePaymentInfo();
}
}
Wrap the current contents of your OnLoad method in:
if (!Page.IsPostBack)
{
// Code in here will only be executed when the page is *not* being loaded by a postback
}
This is because, as per the ASP.NET Page Life Cyle, the things that you care about in this instance happen in this order:
Load - During load, if the current request is a postback, control
properties are loaded with information
recovered from view state and control
state.
Postback event handling - If the request is a postback, control event
handlers are called. After that, the
Validate method of all validator
controls is called, which sets the
IsValid property of individual
validator controls and of the page.
So what happens is (somewhat simplified):
You click the image button, triggering the postback.
The data from your form is loaded into your controls.
Your OnLoad method overwrites the values in the controls to clear them.
Your click handler is run, but because of step 3 it sees empty values.
As others have sort-of mentioned, it wouldn't necessarily be a bad thing to refactor your OnLoad method whilst you're doing this. At the moment you seem to have it doing two distinct things:
Clearing the text fields
Setting the visibility of fields
It might be worth separating this into one or two (depending on if the visibility setting and field clearing will be done independently) separate methods and adjusting your OnLoad method so it looks like this:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!Page.IsInPostBack)
{
SetFieldVisibility();
ClearFields();
}
}
Page_Load always occurs.
See the documentation on the Page Lifecycle
What you need to do is check to see if the Page_Load is being triggered by a Postback.
private void Page_Load(object sender, System.EventArgs e)
{
if(!Page.IsPostBack)
{
///do stuff in here that you want to occur only on the first lad.
}
else
}
// code that you want to execute only if this IS a postback here.
{
}
// do stuff you want to do on Page_Load regardless of postback here.
}
You can use the IsPostBack property of the Page as follows:
protected override void OnLoad(EventArgs e) {
if (!Page.IsPostBack) {
EmptyTextBoxes();
}
}
Have you tried wrapping the form reset code in a check to see if the page is a postback?
if(!Page.IsPostback) {
// Do form reset here
}
You thought about using the IsPostBack page variable?
protected override void OnLoad(EventArgs e)
{
if(!IsPostBack){
//all your logic here.
}
}
if it's the case, you might use a databound control and set it to insert mode

the checkbox event is not triggerd?

i have created checkbox event maually.
chkCheckBox1.CheckedChanged += new EventHandler(chkCheckBox1_CheckedChanged);
this event is not triggered,in pageload i have put
(!page.ispostback)
{
}
so when i clik the check box it goes to the page load and not going to the evnt
protected void chkCheckBox1_CheckedChanged(object sender, EventArgs e)
{
..........
}
the checkbox event is not triggerd..
Have you enabled AutoPostBack property on your control?
By default this is set to False when you add a checkbox control to your page. Try setting it to true.
Set the Autopostback property to true.
chkCheckBox1.CheckedChanged += new EventHandler(chkCheckBox1_CheckedChanged);
You have to wire up this event on every call to the page so if you have put this inside of the if(!Page.IsPostBack) then put it outside.
Take a look at this article Adding a dynamic control to a placeholder control and wire up the event. It shows an extra step for making things totally dynamic but the principles stay the same for what you're after.
Grz, Kris.
To trigger the following event
protected void chkCheckBox1_CheckedChanged(object sender, EventArgs e)
{
..........
}
Set the checkbox autopostback property to TRUE

using FormView to insert

I have a formview control, and on the ItemCreated event, I am "priming" some of the fields with default values.
However, when I try to use the formview to insert, before the ItemInserting event gets called, for some reason it calls ItemCreated first. That results in the fields being over-written with the default values right before the insert happens.
How do I get it to not call the ItemCreated event before the ItemInserting event?
you need to use formview Databound event instead of formview ItemCreated event to set values, try like
protected void frm_DataBound(object sender, EventArgs e)
{
if (frm.CurrentMode == FormViewMode.Edit)//whatever your mode here is.
{
TextBox txtYourTextBox = (TextBox)frm.FindControl("txtYourTextBox");
txtYourTextBox.Text// you can set here your Default value
}
}
Also check this thread of similare issue
FormView_Load being overwritten C# ASP.NET
You cannot change the order in which the events fire. However, you should probably wrap the code that sets the default values inside !IsPostBack so that it doesn't reset your values for example:
protected void FormView_ItemCreated(Object sender, EventArgs e)
{
if(!IsPostBack)
{
//Set default values ...
}
}
Try checking the CurrentMode property of the form view.
void FormView_ItemCreated(object sender, EventArgs e)
{
if (FormView.CurrentMode != FormViewMode.Insert)
{
//Initialize your default values here
}
}

Categories