I am creating the same button twice: once on Page_Load, and another on: Page_PreRender.
I expected to see the same behavior, however, the buttons created on Page_PreRender doesn't work the way intended. (i.e. property "causeValidation" remains true).
"I want to disable "causeValidation" for the button in page_preRender, and i want it there in PreRender. Also, I want the Button_Click function to execute for both buttons, currently it does only for button created on "Page_load" ".
I am looking for a solution or an explanation for this behavior.
Thank You.
Take a look at the code:
protected void Page_Load(object sender, EventArgs e)
{
form1.Controls.Add(GetButton("Button1", "Click"));
}
protected void page_PreRender(object sender, EventArgs e)
{
form1.Controls.Add(GetButton("Button3", "Click"));
}
private Button GetButton(string id, string name)
{
Button b = new Button();
b.Text = name;
b.ID = id;
b.CausesValidation = false;
b.Click += new EventHandler(Button_Click);
b.OnClientClick = "ButtonClick('" + b.ClientID + "')";
return b;
}
protected void Button_Click(object sender, EventArgs e)
{
ClientScript.RegisterClientScriptBlock(this.GetType(), ((Button)sender).ID, "<script>alert('Button_Click');</script>");
Response.Write(DateTime.Now.ToString() + ": " + ((Button)sender).ID + " was clicked");
}
and here is the javascript:
<script type="text/javascript">
function ButtonClick(buttonId) {
alert("Button " + buttonId + " clicked from javascript");
}
</script>
Update:
let me add this: Both buttons execute the client's script. This means that buttons are created. "see function GetButton() ".
Also, the reason why i have the button created "on preRender" instead of "on Page_Load" is that: if i have a form used to enter data into a table dynamically, and i add the data on button click, the the page will PostBack first, then execute the event handler, (i.e the data is added to the table but will show on NEXT postBack). So, PreRender is used to show the table AFTER it is updated by the button_click event.
I hope this addition is useful
As you see from this image, that represents asp.net page life cycle (copied from MSDN), Event Handling precedes PreRender. So, in order to fire Button_Click the button itself has to be created before the Event Handling. Page PreInit is a preferred place to add dynamic controls.
you can see it yourself, just add breakpoints at Page_Load, Page_PreRender, Button_Click. notice the order there are triggered?
Check asp.net page lifecycle: events are handled after page load and before PreRender.
ASP.NET cannot handle an event involving a control that does not yet exists.
Related
I created a button from code behind:
Panel dynamicPanel = new Panel();
Button dynamicButton = new Button();
dynamicButton.Text = "View";
dynamicButton.Click += new EventHandler(dynamicButton_Click);
dynamicPanel.Controls.Add(dynamicButton);
dynamicDiv.Controls.Add(dynamicPanel);
and the OnClick method:
protected void dynamicButton_Click(object sender, EventArgs e)
{
Response.Write("view button response");
string script = "alert(\"view clicked.\");";
ScriptManager.RegisterStartupScript(this, GetType(),
"ServerControlScript", script, true);
}
When I click the button, there is postback (IsPostback with Javascript alert) but the EventHandler is not fired. I can say that content that was visible on the page disappears if that is a clue.
I need to create this in a custom protected void method.
Your code looks a bit weird to me, but as for the problem "When I click the button, the method is not fired": Try renaming the method dynamicREGButton_Click() to dynamicButton_Click().
I assume you have a method dynamicButton_Click() in your code already; otherwise, you could not compile. However, the method you register via dynamicButton.Click += new EventHandler(...); is the method you call. The code you showed us doesn't match in that regard.
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.
I'm working on Visual Studio, in C# language
I would like to ask if there's someway to go back to get the ButtonX.Text I pressed on the previous page, some sort of Login without a password.
Basically I need a worker to specify which person he is by clicking on their name (button) then it goes foward to the next page I have a label on the MasterPage but it resets everytime it goes on a next page what I would like to do is keep the info there
If you need some code tell me.
Thanks
You could use session variables?
On the button click handler on the first page...
protected void button_Click(object sender, EventArgs e)
{
Session["Worker"] = button.Text;
}
Then on the second page...
Label.Text = Session["Worker"];
Based-off your reply to Zollistic's answer, you could do this...
Apply this event to all your all your worker buttons...
protected void button_Click(object sender, EventArgs e)
{
if (Session["Worker"] == null) Session["Worker"] = "";
Session["Worker"] += button.Text + ",";
}
Now Session["Worker"] has a character-delimited list of all the clicked buttons. The character in this example is a comma; but you can change it to whatever you want (i.e. a pipe "|").
Currently, I am doing a project for students' hostel and now I have to implement some search strategies about students.Here I have to create a button dynamically when the user clicks on the another server button in .aspx page and accordingly I have to create the onclick event handler for the newly created button. The code-snippet that I used is:
protected void btnsearchByName_Click(object sender, EventArgs e)
{
TextBox tbsearchByName = new TextBox();
Button btnsearchName = new Button();
tbsearchByName.Width = 250;
tbsearchByName.ID = "tbsearchByName";
tbsearchByName.Text = "Enter the full name of a student";
btnsearchName.ID = "btnsearchName";
btnsearchName.Text = "Search";
btnsearchName.Click += new EventHandler(this.btnsearchName_Click);
pnlsearchStudents.Controls.Add(tbsearchByName);
pnlsearchStudents.Controls.Add(btnsearchName);
}
protected void btnsearchName_Click(object sender, EventArgs e)
{
lblsearch.Text = "btnsearchName_Click event fired in " + DateTime.Now.ToString();
}
Here, the problem is newly created eventHandler doesnot get fired. I have gone through this site and looked several questions and answers and also gone through the page life-cycle and they all say that the dynamic button should be on Init or Pre_init, but my problem is I have to create it when another button is clicked, how can it be possible?
You need to add the click handler for the button on every postback.
you could look for the button in the search students panel on page load or try the page OnInit() method to add the handler when its created.
Also check here:
Dynamically added ASP.NET button click handler being ignored
and here:
asp.net dynamically button with event handler
and here:
asp:Button Click event not being fired
(all of which give similar suggestions)
Try this http://msdn.microsoft.com/ru-ru/library/system.web.ui.webcontrols.button.command(v=vs.90).aspx
btnsearchName.Command += new CommandEventHandler(this.btnsearchName_Click);
btnsearchName.CommandName = "Click";
You need to recreate the button and attach the event handler every time. For this, create a list of button and save it on session. On page load, go through the List and create the button every time
public Button create_button()
{
btnsearchName.ID = "btnsearchName";
btnsearchName.Text = "Search";
btnsearchName.Click += new EventHandler(this.btnsearchName_Click);
return btnsearchName;
}
public TextBox create_textbox()
{
TextBox tbsearchByName = new TextBox();
Button btnsearchName = new Button();
tbsearchByName.Width = 250;
tbsearchByName.ID = "tbsearchByName";
tbsearchByName.Text = "Enter the full name of a student";
return tbsearchByName;
}
protected void btnsearchByName_Click(object sender, EventArgs e)
{
TextBox tbsearchByName = create_textbox();
Button btnsearchName = create_button();
//add to panels
pnlsearchStudents.Controls.Add(tbsearchByName);
pnlsearchStudents.Controls.Add(btnsearchName);
//add to session
List<Button> lstbutton = Session["btn"] as List<Button>
lstbutton.add(btnsearchName);
//similarly add textbox
//again add to session
Session["btn"] = lstbutton
}
public override page_load(object sender, eventargs e)
{
//fetch from session, the lstButton and TextBox and recreate them
List<Button> lstbutton = Session["btn"] as List<Button>;
foreach(Button b in lstbutton)
pnlsearchStudents.Controls.Add(b);
//similar for textbox
}
I am not sure but may be you have to override the OnInit() method like this.
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
}
You just need to add this code on ready state of jquery code and it will work fine for the dynamic button too
$(document).ready(function(){
$('input#tbsearchByName').click(function(){
// code goes here
});
});
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";
}
}