Before I begin, I have already seen this question about a very similar topic (as well as this one and this one), none of which answer my question completely. I already understand the concepts presented in these questions/answers, but I have more questions.
A) What happens if you have multiple controls with AutoPostBack="false" and you change a number of them before a postback? Take the following brief example (assume that everything else needed for the page is written correctly and trivially; e.g., Page_Load):
Default.aspx:
<asp:DropDownList ID="ddlFoo" runat="server"
OnSelectedIndexChanged="ddlFoo_Changed" AutoPostBack="false" >
<asp:ListItem Text="a" />
<asp:ListItem Text="b" />
<asp:ListItem Text="c" />
</asp:DropDownList>
<asp:DropDownList ID="ddlBar" runat="server"
OnSelectedIndexChanged="ddlBar_Changed" AutoPostBack="false" >
<asp:ListItem Text="1" />
<asp:ListItem Text="2" />
<asp:ListItem Text="3" />
</asp:DropDownList>
<asp:Button ID="btnQux" runat="sever" Text="Click for PostBack" OnClick="btnQux_Click"
Default.aspx.cs:
protected void ddlFoo_Changed(object sender, EventArgs e)
{
Response.Write("ddlFoo changed to " + ddlFoo.Text + ". ");
}
protected void ddlBar_Changed(object sender, EventArgs e)
{
Response.Write("ddlBar changed to " + ddlBar.Text + ". ");
}
protected void btnQux_Changed(object sender, EventArgs e) { }
Now, say you change ddlFoo to 3 and then ddlBar to b. Then, you click btnQux. You get the following output from Response.Write after clicking:
ddlBar changed to b. ddlFoo changed to 3.
Why does this happen? Do the OnSelectedIndexChanged methods get put into a stack to be called once a postback happens?
B) Why does my webpage load much more quickly when I use this approach and set AutoPostBack="false" for most of my controls? To be specific, I did this for a
CheckBox, a DropDownList, and a TextBox in a GridView, which retrieved ~1200 rows and 27 columns of data and took 10s in VS2008 debug mode versus 310s before. Why would the load/refresh time be so much faster?
EDIT: I released the code earlier this afternoon, and there was no significant difference between the load time of the old (AutoPostBack="true") and new (AutoPostBack="false") versions. I think that perhaps the debugger was doing something extra, which caused the large jump in load time. A better way to rephrase question B) might be this then: What could the debugger have been doing to cause this large jump in load time?
Warning: I'm no ASP.NET expert... If this turns out to be garbage, I'll delete it :)
A) I believe you will see the new values of all the controls, whenever the postback ends up happening, including all the change events, just as you described. The values have changed, after all - the AutoPostBack just affects the timing (and whether the postback occurs at all, of course).
B) There's more Javascript in the HTML delivered with AutoPostBack = True on all the controls, but not enough to make that enormous difference. As noted in your edit, it looks like that was a transient issue anyway - we can't really explain transient issues without more diagnostics.
You can use Fiddler to see what data is moving between client and server.
A. With fiddler you can easily see what data is sent to the server.
For example:
If you have DropDownList ddlFoo, when you click on button, you actually post this information:
POST http:// [server]:[port]/[resource.aspx] HTTP/1.1 Host: [server]:[port]
[Headers...]
_VIEWSTATE[viewstate data stored in html as hidden field value]&_EVENTVALIDATION=[event validaion
data]&ddlFoo=selecteItem&button1=ButtonText
When ASP.NET receives request, it compares ddlFoo's value and invokes it's event.
B. When you set AutoPostBack to true, then this javascript function will be generated:
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
And onchange attribute will be added to ddlFoo. So whenever you change DropdownList item, onchange event will be fired and __doPostBack function will be called, which will auto post back to the server.
Both answers you have gotten so far are correct. The simplified version of it is this:
A) When the form is finally POST'ed to the server, the server compares the form's current state with the ViewState and responds accordingly.
B) Enabling AutoPostBack causes javascript to be generated, and this javascript submits the form (which then triggers the postback).
Why does this happen? Do the OnSelectedIndexChanged methods get put
into a stack to be called once a postback happens?
Events that do not immediately post back (in your case ddlFoo_Changed and ddlBar_Changed) are cached.
Then those cached/pending events are raised along with btnQux's click event, when a page is posted back (by btnQux's click event).
You can read more here - ASP.NET Server Control Event Model
Related
I am using an aspx page, single file web form, to capture user input on the client side via a dropdown box and then modify available text box fields (simple example...if client selects dropbox item 1, then text box 1 is enabled; if client selects dropbox item 2, then text box 2 is enabled).
The dropbox html code looks like this and works perfectly with exception of event handler OnSelectedIndexChanged:
<asp:DropDownList ID="FAQ" runat="server" ViewStateMode="Enabled" EnableViewState="true" Width="354px" AutoPostBack="true" OnSelectedIndexChanged="selectedFAQ()" >
<asp:ListItem Text="Please Select" Value="Default"></asp:ListItem>
<asp:ListItem Text="Text 1 Here" Value="FAQ1"></asp:ListItem>
<asp:ListItem Text="Text 2 Here" Value="FAQ2"></asp:ListItem>
<asp:ListItem Text="Text 3 Here" Value="FAQ3"></asp:ListItem>
</asp:DropDownList>
The function selectedFAQ() is defined in the script section:
function selectedFAQ()
{
//code to enable/disable text fields here
}
I have seen several different posts and answers to this issue, but it seems that the posts I have seen contained an aspx and aspx.cs file...my page is the single web form.
I also want to mention that the page is not my creation, I am simply trying to add additional functionality to it. And finally, there is a "inherits" tag that references a 3 year old dll that I do not have the code for.
If this issue has been addressed, please point me to the correct question/answer and thanks. If not, please assist if able. I can provide any additional code if needed. Thanks.
What you currently have is a subscription to a postback event. That is, function that should handle change of index in server side code. However your fucntion is actually a javascript one and executes on a client side. To call that, you need to assign a different attribute of the drop down control:
onchange="selectedFAQ();"
And remove handling of OnSelectedIndexChanged, you won't be able to define a server side handler without code behind access anyway.
I have a Webpart that contains a couple of dropdowns on an update panel. There is a submit button that has the PostBackUrl set to a sharepoint Application Page
<asp:DropDownList ID="ClassSelector" runat="server" Enabled="False"
AutoPostBack="True" onselectedindexchanged="ClassSelector_SelectedIndexChanged">
<asp:ListItem Selected="True" Value="-null-">Select Class...</asp:ListItem>
<asp:ListItem Value="1">Class 1</asp:ListItem>
</asp:DropDownList>
<asp:Button ID="btnSubmit" runat="server" Text="Show Page" Enabled="False"
PostBackUrl="~/_layouts/MyWebParts/MyAppPage.aspx" />
This works in redirecting the browser to the Application Page I have created, but I am having trouble accessing the form data.
On the Page_Load function of the Application Page I have the following debugging code.
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = "";
foreach (String s in Page.Request.Form.AllKeys)
{
Label1.Text += s + ": " + Page.Request.Form[s] + "<br />";
}
}
This shows that the data I need has in fact been posted to the page.
ctl00$m$g_24a73cf8_8190_4ddb_b38b_bf523b12dbd3$ctl00$SemesterSelector: 28
ctl00$m$g_24a73cf8_8190_4ddb_b38b_bf523b12dbd3$ctl00$ClassSelector: 11-0021-A
But when I try to access this as:
Page.Request.Form["ClassSelector"]
Nothing is returned. I know I must be missing something simple here, but I am not sure what.
Any help is greatly appreciated.
Ah, the ASP.NET master page prefix problem! One of my favorites.
The master page for your application page puts a prefix in front of your server-side controls so that they will be unique. If you end up access your control via the Form collection, you have to access it using not only the control ID, but also the ContentPlaceholder prefix. That's why you see such a large ID dumped out of your debugging logic.
If you want to programmatically get to the ID of the control, you can use FindControl, but you'll have to target the apppropriate content placeholder scope for this. Here's a good tutorial/explanation here (which really emphasizes how complex this can get!).
Of course, the other option you can use is just hard-coding the control id based on what you're seeing from your debugging code...but that won't be reliable if you change content placeholders or more your control to a different container.
I guess the answer depends on how static your controls will be.
Hope this helps. Good luck!!
Well to access it that way you would have to use
Page.Request.Form["ctl00$m$g_24a73cf8_8190_4ddb_b38b_bf523b12dbd3$ctl00$ClassSelector"]
As you can actually see from your code where you set the label text to s plus Request.Form[s]
I have an <asp:DropDownList> witch gets filled by static list items.
<asp:DropDownList ... OnDataBound="handlerMethod">
<asp:ListItem Value="..." Text="..." />
<asp:ListItem Value="..." Text="..." />
<asp:ListItem Value="..." Text="..." />
</asp:DropDownList>
The problem is that the OnDataBound event does not get triggered when the list is filled. I need it to trigger to fill some other data from the list items that are in the dropdown.
The documentation says:
This method notifies a server control that any data binding logic associated with the control has completed.
My eyes are on this "logic" word which makes me thing that i missed the point on when the event is triggered
But if that is the case, how can I get the event triggered or what other event can I use to know when the list has finished beeing filled?
Normally this means that you have deleted the AutoEventWireup="true" or set it to false, and that's why it's not wiring up the event.
It can also mean that there is something wrong in the javascript that does not allow anymore code to run. Open the inspector (Chrome, Safari or Firebug in Firefox - Do not rely on IE Developer tools) and see if you have any javascript errors that can cause the page to stop.
It can also mean that the handlerMethod is not correctly set up, best way is to delete the html part OnDataBound="handlerMethod" and the code behind of this method, then go to design view, open the Properties window in the Events and double click the OnDataBound, it will add the event correctly. Set up a break point there and run in debug with debug="true" in your web.config file.
I have placed a list box and a text box with Selected Index Changed and Text Changed event respectively in an aspx page. Now If I write something in text box and then with out clicking elsewhere select a value in list box, then first Text Changed event of text box is called then selected Index Change event of list box is called. After that again Text Change event of text box is called. Can any body give some insight why this happening??
Below is the markup:
<asp:ListBox ID="ListBox1" runat="server" AutoPostBack="true" OnSelectedIndexChanged="ListBox_IndexChanged">
<asp:ListItem Text="abc" />
<asp:ListItem Text="def" />
</asp:ListBox>
<asp:TextBox ID="TextBox1" runat="server" AutoPostBack="true" OnTextChanged="Text_Changed" />
Code behind:
namespace WebApplication1
{
public partial class _Default : System.Web.UI.Page
{
protected void ListBox_IndexChanged(object sender, EventArgs e)
{
}
protected void Text_Changed(object sender, EventArgs e)
{
}
}
}
The problem/issue is that AutoPostBack works by attaching JavaScript events to your controls. Each browser handles JavaScript a little bit differently, so there's no real guarantee to the ordering.
When I try your code in Google Chrome, for example, the following sequence of events occurs:
Request sent to server
ListBox_IndexChanged event gets called
Text_Changed event gets called
Response goes back to client
However, in Internet Explorer 8, I noticed the following sequence:
Request sent to server
Text_Changed event gets called
Response goes back to client
Another request sent to server
ListBox_IndexChanged event gets called
Text_Changed event gets called
2nd Response goes back to client
This isn't a fault of ASP.NET, but just of varying JavaScript implementations across browsers, I suppose.
If you need to rely on a specific sequence of events, AutoPostBack isn't going to cut it. Depending on your situation, I might look at implementing my own JavaScript events using a cross-browser compliant library like jQuery. You could programmatically call back to the server by using the __doPostBack() function.
When a new item is selected the text in the text part of the listbox is replaced with the text of the item. That's why you get the second TextChanged event.
Have run this by my entire dev group to no avail. Seems simple enough, here's the question.
I have a UserControl with a single, non-databound dropdownlist. The UserControl is then dropped onto the masterpage and then also loaded into an inheriting webform that has the control manually loaded onto the page.
No AJAX, straight post-back.
The issue I am running into is that the SelectedIndexChanged event is not firing for the second instance of the DropDownList. The first one fires just fine.
TIA
Here is the code for the ascx:
<asp:dropdownlist id="SelectLanguage" autopostback="true" runat="server" enableviewstate="true">
<asp:listitem>- Select Language -</asp:listitem>
<asp:listitem value="xxx">Netherlands</asp:listitem>
<asp:listitem value="xxx">United Kingdom</asp:listitem>
<asp:listitem value="xxx">United States</asp:listitem>
</asp:dropdownlist>
Here is the CB for the user control:
protected override void OnInit(EventArgs e)
{
SelectLanguage.SelectedIndexChanged += new EventHandler(SelectLanguage_SelectedIndexChanged);
base.OnInit(e);
}
protected void SelectLanguage_SelectedIndexChanged(object sender, EventArgs e)
{
// do something
}
Does the postback actually happen for the second dropdown, or does the page do nothing?
If the postback isn't happening, you have javascript errors on your page.
Not sure exactly how this is, but the FancyBox lightbox jQuery library we're using to do the lightbox effect around the 2nd drop down is somehow messing with the bindings on the back end. No real time to figure out why, just let it be known it does in case anyone else runs into this issue.