Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > ASP .Net > Ajax UpdatePanel DropDownList auto-repeat problem.

Reply
Thread Tools

Ajax UpdatePanel DropDownList auto-repeat problem.

 
 
cmeek1_1999
Guest
Posts: n/a
 
      09-25-2008
Hello,

On a webpage, create an UpdatePanel with two DropDownLists.
Set AutoPostBack of DropDownList1 to true.
In the SelectedIndexChanged method, refill DropDownList2 and set the focus
to DropDownList1 using the ScriptManager SetFocus method.

Use the Visual Studio debugger.
Set a breakpoint on in the (!IsPostBack) part of the PageLoad method.
Start the web application and continue after the breakpoint has been reached.
Press once the down-arrow on the DropDownList1.
An update of DropDownList2 will occur as expected.

Press and hold the down-arrow (or up-arrow) so the auto-repeat sets in.
From time to time (not always) the breakpoint gets reached, which is highly
unexpected.

Two questions.

1) Why does this happen?
2) What can I do to prevent this from happening without losing focus and
auto-repeat functionality?

Regards,

Carlo Mekenkamp

default.aspx.cs
---8<---
using System;
using System.Web.UI.WebControls;

namespace AjaxDdlTest
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DropDownList1.DataBind(); //breakpoint here
DropDownList1.SelectedValue = "0";
DropDownList2.DataBind();
DropDownList1.Focus();
}
}

protected void DropDownList1_SelectedIndexChanged(object sender,
EventArgs e)
{
DropDownList ddl = (DropDownList)sender;
DropDownList2.DataBind();
ScriptManager1.SetFocus(ddl);
}

protected void DropDownList1_DataBinding(object sender, EventArgs e)
{
DropDownList ddl = (DropDownList)sender;
ddl.Items.Clear();
for (int i = 0; i < 200; i++)
{
ddl.Items.Add(i.ToString());
}
}

protected void DropDownList2_DataBinding(object sender, EventArgs e)
{
DropDownList ddl = (DropDownList)sender;
ddl.Items.Clear();
for (int i = int.Parse(DropDownList1.SelectedValue); i < 200; i++)
{
ddl.Items.Add(i.ToString());
}
}
}
}
---8<---
default.aspx
---8<---
<%@ Page Language="C#" AutoEventWireup="true" Codebehind="Default.aspx.cs"
Inherits="AjaxDdlTest._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>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<div>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<aspropDownList ID="DropDownList1" runat="server"
AutoPostBack="true" OnDataBinding="DropDownList1_DataBinding"

OnSelectedIndexChanged="DropDownList1_SelectedInde xChanged" />
<br />
<aspropDownList ID="DropDownList2" runat="server"
AutoPostBack="true" OnDataBinding="DropDownList2_DataBinding" />
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
---8<---
 
Reply With Quote
 
 
 
 
bruce barker
Guest
Posts: n/a
 
      09-25-2008
this is one of the problems of using autopostback with a dropdown.
becuase the onclick/onchange fires as the down arrow is used, a postback
is fired on each selection. any postback causes the dropdown to be built
by the browser.

a quick hack is to have client code attached to the onchange disable the
select, then on rerender enable it again. a better approach is to use a
timer to only fire the postback when the user pauses in selecting. the
best is to not use a postback on a dropdown, but some other ajax method.

-- bruce (sqlwork.com)

cmeek1_1999 wrote:
> Hello,
>
> On a webpage, create an UpdatePanel with two DropDownLists.
> Set AutoPostBack of DropDownList1 to true.
> In the SelectedIndexChanged method, refill DropDownList2 and set the focus
> to DropDownList1 using the ScriptManager SetFocus method.
>
> Use the Visual Studio debugger.
> Set a breakpoint on in the (!IsPostBack) part of the PageLoad method.
> Start the web application and continue after the breakpoint has been reached.
> Press once the down-arrow on the DropDownList1.
> An update of DropDownList2 will occur as expected.
>
> Press and hold the down-arrow (or up-arrow) so the auto-repeat sets in.
> From time to time (not always) the breakpoint gets reached, which is highly
> unexpected.
>
> Two questions.
>
> 1) Why does this happen?
> 2) What can I do to prevent this from happening without losing focus and
> auto-repeat functionality?
>
> Regards,
>
> Carlo Mekenkamp
>
> default.aspx.cs
> ---8<---
> using System;
> using System.Web.UI.WebControls;
>
> namespace AjaxDdlTest
> {
> public partial class _Default : System.Web.UI.Page
> {
> protected void Page_Load(object sender, EventArgs e)
> {
> if (!IsPostBack)
> {
> DropDownList1.DataBind(); //breakpoint here
> DropDownList1.SelectedValue = "0";
> DropDownList2.DataBind();
> DropDownList1.Focus();
> }
> }
>
> protected void DropDownList1_SelectedIndexChanged(object sender,
> EventArgs e)
> {
> DropDownList ddl = (DropDownList)sender;
> DropDownList2.DataBind();
> ScriptManager1.SetFocus(ddl);
> }
>
> protected void DropDownList1_DataBinding(object sender, EventArgs e)
> {
> DropDownList ddl = (DropDownList)sender;
> ddl.Items.Clear();
> for (int i = 0; i < 200; i++)
> {
> ddl.Items.Add(i.ToString());
> }
> }
>
> protected void DropDownList2_DataBinding(object sender, EventArgs e)
> {
> DropDownList ddl = (DropDownList)sender;
> ddl.Items.Clear();
> for (int i = int.Parse(DropDownList1.SelectedValue); i < 200; i++)
> {
> ddl.Items.Add(i.ToString());
> }
> }
> }
> }
> ---8<---
> default.aspx
> ---8<---
> <%@ Page Language="C#" AutoEventWireup="true" Codebehind="Default.aspx.cs"
> Inherits="AjaxDdlTest._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>Untitled Page</title>
> </head>
> <body>
> <form id="form1" runat="server">
> <asp:ScriptManager ID="ScriptManager1" runat="server" />
> <div>
> <asp:UpdatePanel ID="UpdatePanel1" runat="server">
> <ContentTemplate>
> <aspropDownList ID="DropDownList1" runat="server"
> AutoPostBack="true" OnDataBinding="DropDownList1_DataBinding"
>
> OnSelectedIndexChanged="DropDownList1_SelectedInde xChanged" />
> <br />
> <aspropDownList ID="DropDownList2" runat="server"
> AutoPostBack="true" OnDataBinding="DropDownList2_DataBinding" />
> </ContentTemplate>
> </asp:UpdatePanel>
> </div>
> </form>
> </body>
> </html>
> ---8<---

 
Reply With Quote
 
 
 
 
cmeek1_1999
Guest
Posts: n/a
 
      09-26-2008
Thank you for responding.

When I disabled the select on the onchange, the focus was lost,
so that was no good solution.
Setting a timer was a better solution. I implemented it like below.
Or should I make an Ajax Extender to handle this?
Letting another control return was not an option I think.

Regards,

Carlo Mekenkamp

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
string ddl_timeout_id = DropDownList1.ClientID + "_timeoutId";
string ddl_submit = DropDownList1.ClientID + "_submit";
string delayscript =
@"var " + ddl_timeout_id + @"=0;
function " + ddl_submit + @"()
{
clearTimeout(" + ddl_timeout_id + @");
" + ddl_timeout_id + @"=setTimeout('" +
ClientScript.GetPostBackEventReference(DropDownLis t1,
string.Empty).Replace(@"'", @"\'")
+ @"', 500);
return true;
}";
ClientScript.RegisterClientScriptBlock(typeof(_Def ault),
ddl_submit, delayscript, true);
DropDownList1.DataBind(); //breakpoint here
DropDownList1.Attributes["onchange"] = @"return " +
ddl_submit + @"();alert('Bug:No return');";
DropDownList1.SelectedValue = "0";
DropDownList2.DataBind();
DropDownList1.Focus();
}
}


"bruce barker" wrote:

> this is one of the problems of using autopostback with a dropdown.
> becuase the onclick/onchange fires as the down arrow is used, a postback
> is fired on each selection. any postback causes the dropdown to be built
> by the browser.
>
> a quick hack is to have client code attached to the onchange disable the
> select, then on rerender enable it again. a better approach is to use a
> timer to only fire the postback when the user pauses in selecting. the
> best is to not use a postback on a dropdown, but some other ajax method.
>
> -- bruce (sqlwork.com)
>
> cmeek1_1999 wrote:
> > Hello,
> >
> > On a webpage, create an UpdatePanel with two DropDownLists.
> > Set AutoPostBack of DropDownList1 to true.
> > In the SelectedIndexChanged method, refill DropDownList2 and set the focus
> > to DropDownList1 using the ScriptManager SetFocus method.
> >
> > Use the Visual Studio debugger.
> > Set a breakpoint on in the (!IsPostBack) part of the PageLoad method.
> > Start the web application and continue after the breakpoint has been reached.
> > Press once the down-arrow on the DropDownList1.
> > An update of DropDownList2 will occur as expected.
> >
> > Press and hold the down-arrow (or up-arrow) so the auto-repeat sets in.
> > From time to time (not always) the breakpoint gets reached, which is highly
> > unexpected.
> >
> > Two questions.
> >
> > 1) Why does this happen?
> > 2) What can I do to prevent this from happening without losing focus and
> > auto-repeat functionality?
> >
> > Regards,
> >
> > Carlo Mekenkamp
> >
> > default.aspx.cs
> > ---8<---
> > using System;
> > using System.Web.UI.WebControls;
> >
> > namespace AjaxDdlTest
> > {
> > public partial class _Default : System.Web.UI.Page
> > {
> > protected void Page_Load(object sender, EventArgs e)
> > {
> > if (!IsPostBack)
> > {
> > DropDownList1.DataBind(); //breakpoint here
> > DropDownList1.SelectedValue = "0";
> > DropDownList2.DataBind();
> > DropDownList1.Focus();
> > }
> > }
> >
> > protected void DropDownList1_SelectedIndexChanged(object sender,
> > EventArgs e)
> > {
> > DropDownList ddl = (DropDownList)sender;
> > DropDownList2.DataBind();
> > ScriptManager1.SetFocus(ddl);
> > }
> >
> > protected void DropDownList1_DataBinding(object sender, EventArgs e)
> > {
> > DropDownList ddl = (DropDownList)sender;
> > ddl.Items.Clear();
> > for (int i = 0; i < 200; i++)
> > {
> > ddl.Items.Add(i.ToString());
> > }
> > }
> >
> > protected void DropDownList2_DataBinding(object sender, EventArgs e)
> > {
> > DropDownList ddl = (DropDownList)sender;
> > ddl.Items.Clear();
> > for (int i = int.Parse(DropDownList1.SelectedValue); i < 200; i++)
> > {
> > ddl.Items.Add(i.ToString());
> > }
> > }
> > }
> > }
> > ---8<---
> > default.aspx
> > ---8<---
> > <%@ Page Language="C#" AutoEventWireup="true" Codebehind="Default.aspx.cs"
> > Inherits="AjaxDdlTest._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>Untitled Page</title>
> > </head>
> > <body>
> > <form id="form1" runat="server">
> > <asp:ScriptManager ID="ScriptManager1" runat="server" />
> > <div>
> > <asp:UpdatePanel ID="UpdatePanel1" runat="server">
> > <ContentTemplate>
> > <aspropDownList ID="DropDownList1" runat="server"
> > AutoPostBack="true" OnDataBinding="DropDownList1_DataBinding"
> >
> > OnSelectedIndexChanged="DropDownList1_SelectedInde xChanged" />
> > <br />
> > <aspropDownList ID="DropDownList2" runat="server"
> > AutoPostBack="true" OnDataBinding="DropDownList2_DataBinding" />
> > </ContentTemplate>
> > </asp:UpdatePanel>
> > </div>
> > </form>
> > </body>
> > </html>
> > ---8<---

>

 
Reply With Quote
 
cmeek1_1999
Guest
Posts: n/a
 
      09-27-2008
I tried writing an Ajax control (my first one) to do it, because I had
troubles with the script inside a FormView and I wanted the first postback
without delay.
Be sure to make AutoPostBackDelayBehavior.js an embedded resource and let
the ClientScriptResource attribute point to the right place.
Let the TargetControlId be the Id of the DropDownList, and it seems to work.

Thanks again.

Carlo Mekenkamp

AutoPostBackDelayExtender.cs
---8<---
using System;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.ComponentModel;
using System.ComponentModel.Design;
using AjaxControlToolkit;

[assembly:
System.Web.UI.WebResource("AutoPostBackDelay.AutoP ostBackDelayBehavior.js",
"text/javascript")]

namespace AutoPostBackDelay
{
[Designer(typeof(AutoPostBackDelayDesigner))]
[ClientScriptResource("AutoPostBackDelay.AutoPostBa ckDelayBehavior",
"AutoPostBackDelay.AutoPostBackDelayBehavior.j s")]
[TargetControlType(typeof(Control))]
public class AutoPostBackDelayExtender : ExtenderControlBase
{
// TODO: Add your property accessors here.
//
[ExtenderControlProperty]
[DefaultValue(500)]
public int DelayTime
{
get
{
return GetPropertyValue("DelayTime", 500);
}
set
{
SetPropertyValue("DelayTime", value);
}
}
[ExtenderControlProperty]
[DefaultValue(600)]
public int ResetTime
{
get
{
return GetPropertyValue("ResetTime", 600);
}
set
{
SetPropertyValue("ResetTime", value);
}
}

/// <summary>
/// Specifies the script to run to initiate a postback
/// </summary>
[ExtenderControlProperty]
[ClientPropertyName("postBackScript")]
[DefaultValue("")]
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public string PostBackScript
{
get
{
return GetPropertyValue("PostBackScript", string.Empty);
}
set
{
SetPropertyValue("PostBackScript", value);
}
}

protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
PostBackScript =
Page.ClientScript.GetPostBackEventReference(Target Control, "");
}
}
}
---8<---
AutoPostBackDelayDesigner.cs
---8<---
using System.Web.UI.WebControls;
using System.Web.UI;

namespace AutoPostBackDelay
{
class AutoPostBackDelayDesigner :
AjaxControlToolkit.Design.ExtenderControlBaseDesig ner<AutoPostBackDelayExtender>
{


}
}
---8<---
AutoPostBackDelayBehavior.js
---8<---
Type.registerNamespace('AutoPostBackDelay');

AutoPostBackDelay.AutoPostBackDelayBehavior = function(element) {
AutoPostBackDelay.AutoPostBackDelayBehavior.initia lizeBase(this,
[element]);

// TODO : (Step 1) Add your property variables here
this._DelayTimeValue = 500;
this._ResetTimeValue = 600;
this._CurrentDelayTimeValue = 0;
this._DelayId = 0;
this._ResetId = 0;
// Script to call to initiate a postback
this._postBackScript = null;
this._changeHandler = null;
this._oldScript = null;
}
AutoPostBackDelay.AutoPostBackDelayBehavior.protot ype = {
initialize : function() {
AutoPostBackDelay.AutoPostBackDelayBehavior.callBa seMethod(this,
'initialize');

var element = this.get_element();

// Attach the handler
this._changeHandler = Function.createDelegate(this, this._onChange);
$addHandler(element, "change", this._changeHandler);

this._oldScript = element.getAttribute("onchange");
if (this._oldScript) {
element.setAttribute("onchange", null);
}
// TODO: Add your initalization code here
},

dispose : function() {
// TODO: Add your cleanup code here
clearTimeout(this._ResetId);
clearTimeout(this._DelayId);
this._CurrentDelayTimeValue = 0;
// Detach event handlers
if (this._changeHandler) {
$removeHandler(this.get_element(), "change", this._changeHandler);
this._changeHandler = null;
}

if (this._oldScript) {
this.get_element().setAttribute("onchange", this._oldScript);
this._oldScript = null;
}

AutoPostBackDelay.AutoPostBackDelayBehavior.callBa seMethod(this,
'dispose');
},

// TODO: (Step 2) Add your property accessors here
_onChange : function() {
var e = this.get_element();
if (e) {
clearTimeout(this._ResetId);
clearTimeout(this._DelayId);
this._DelayId = setTimeout(Function.createDelegate(this,
this._postBack), this._CurrentDelayTimeValue);
this._ResetId = setTimeout(Function.createDelegate(this,
this._reset), this._ResetTimeValue);
this._CurrentDelayTimeValue = this._DelayTimeValue;
return false;
}
},

_reset : function() {
this._CurrentDelayTimeValue = 0;
},

_postBack : function() {
if (this._postBackScript) {
eval(this._postBackScript);
}
},

get_postBackScript : function() {
/// <value type="String">
/// Script to run to initiate a postback
/// </value>
return this._postBackScript;
},
set_postBackScript : function(value) {
if (this._postBackScript != value) {
this._postBackScript = value;
this.raisePropertyChanged('postBackScript');
}
},

get_DelayTime : function() {
return this._DelayTimeValue;
},
set_DelayTime : function(value) {
this._DelayTimeValue = value;
},

get_ResetTime : function() {
return this._ResetTimeValue;
},
set_ResetTime : function(value) {
this._ResetTimeValue = value;
}
}
AutoPostBackDelay.AutoPostBackDelayBehavior.regist erClass('AutoPostBackDelay.AutoPostBackDelayBehavi or', AjaxControlToolkit.BehaviorBase);
---8<---

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Large dropDownList slow in UpdatePanel Don ASP .Net 5 09-02-2009 09:02 AM
Triggering an UpdatePanel with a trigger located outside of the UpdatePanel Nathan Sokalski ASP .Net 1 06-15-2009 06:23 PM
refresh an updatePanel in an other updatePanel fran_j_diaz@yahoo.fr ASP .Net 3 08-08-2007 06:30 AM
Ajax Problem: UpdatePanel with dropdownlist jumps to bottom of the page retroman80s ASP .Net 2 03-05-2007 04:56 AM
AJAX IDE and AJAX TOOL--The Release of JoyiStar AJAX WebShop 3 Beta minnie Java 1 12-13-2006 06:29 AM



Advertisments