I’ve been doing C# for years but ASP.NET for not so long and this has me stumped.
In my troubleshooting example I have a dropdownlist in an ASP.NET page, it has four items in it, I have a serverside event that fires on selectedindexchanged, it all works great in this scenario.
However, if (as i have in my evolved code) I set a Javascript handler for the ‘onchange’ event, (which launches an alert) the alert works fine, but the server side event no longer fires… I’m sure I’m missing something obvious.
Important notes: Autopostback is set to true on the dropdownlist control, viewstate is enabled, the Javascript event handler returns true
Anyone?
It’s not that I have to manually wire up the __doPostBack is it?
Any help greatly appreciated.
Edit
ok here is the code first the codebehind
using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Text; namespace TestEvents { public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } protected override void OnPreRender(EventArgs e) { ClientScriptManager csm = Page.ClientScript; if (!csm.IsClientScriptBlockRegistered('NotesChangeScript')) { StringBuilder sb = new StringBuilder(); sb.Append('\r\n <script type=\'text/javascript\'> \r\n'); sb.Append(' //<![CDATA[ \r\n'); sb.Append(' var changesCount = 0; \r\n'); sb.Append(' function selection_handler()\r\n'); sb.Append('{ \r\n'); sb.Append(' changesCount += 1;\r\n'); sb.Append(' alert('i changed on the client!'); \r\n'); sb.Append(' return true; \r\n'); sb.Append(' } \r\n'); sb.Append(' function SetUpNotesHandler() \r\n'); sb.Append('{ \r\n'); sb.Append(' var ctrls = document.getElementsByTagName(\'SELECT\');\r\n'); sb.Append(' for(i=0;i<ctrls.length;i++)\r\n'); sb.Append(' {\r\n'); sb.Append(' ctrls[i].onchange = selection_handler; \r\n'); sb.Append(' }\r\n'); sb.Append('}\r\n'); sb.Append(' //]]> \r\n'); sb.Append('</script>'); csm.RegisterClientScriptBlock(this.GetType(), 'NotesChangeScript', sb.ToString(), false); StringBuilder initScript = new StringBuilder(); initScript.Append('<script type=\'text/javascript\' >\r\n'); initScript.Append(' //<![CDATA[\r\n'); initScript.Append(' SetUpNotesHandler(); \r\n'); initScript.Append(' //]]> \r\n'); initScript.Append('</script> \r\n'); csm.RegisterStartupScript(this.GetType(), 'StartUpKey', initScript.ToString(),false); base.OnPreRender(e); } } protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e) { Response.Write('i hit the server event'); } }
}
and here is the markup for the page
<%@ Page Language='C#' AutoEventWireup='true' CodeBehind='Default.aspx.cs' Inherits='TestEvents._Default' %> <!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'> <html xmlns='http://www.w3.org/1999/xhtml' > <head runat='server'> <title>problem</title> </head> <body> <form id='form1' runat='server'> <div> <asp:DropDownList ID='DropDownList1' runat='server' AutoPostBack='True' OnSelectedIndexChanged='DropDownList1_SelectedIndexChanged'> <asp:ListItem>Numero Uno</asp:ListItem> <asp:ListItem>Numer Deux</asp:ListItem> <asp:ListItem>Number Three</asp:ListItem> <asp:ListItem>Nomina Quatros</asp:ListItem> </asp:DropDownList> <asp:HiddenField ID='hdnFieldChange' runat='server' /> </div> </form> </body> </html>
ok, firstly, thanks to ScarletGarden for making it clear what the problem was, i had assumed as much but its nice when someone confirms your suspicions.
Secondly, apologies to those who see this as some sort of n00b question and find the whole premise of this question stupid, i really couldnt find any articles clarifying this specific problem…
Thirdly, i have now worked out how to do this in Javascript (although scarlet gardens solution is a lot simpler in pretty much every case) although the attributes.add approach (as scarletGarden suggested) may suffer if you had multiple handlers and needed them to fire in some sort of sequence.
Having had a little dig in reflector, Attributes.Add adds event references by semi colon separating them, so this clearly works as it preserves any handlers that are already declared and semi-colon separates the one(s) you add.
In javascript this kind of chaining (multicasting of a sort) requires that DOM level 2 functionality is used (the javascript bible was useful for identifying this), it should be no surprise that Mozilla and IE have a different way of achieving the same thing and so, in order to add a js handler and preserve the event handling in codebehind, the line in my example above that says
needs to be replaced by the following (before people get precious about this example i do have a big caveat for this, further down)
attachEvent works in IE, addEventListener in Firefox (note the different names for the events, Mozilla preferring to drop the ‘on’
Adding events like this works in a LIFO (last in First Out) manner, there are many alternatives to sequencing events in this manner using more elaborate javascript, covered in an excellent, if slightly confusing thread (because of the way it starts) here http://codingforums.com/showthread.php?t=154673
I hope this stuff enlightens others as much as me, this is the thread i was looking for when i first hit the problem and now i feel a bit stupid, but hey ho