Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   ASP .Net (http://www.velocityreviews.com/forums/f29-asp-net.html)
-   -   Ajax UpdatePanel DropDownList auto-repeat problem. (http://www.velocityreviews.com/forums/t636942-ajax-updatepanel-dropdownlist-auto-repeat-problem.html)

cmeek1_1999 09-25-2008 08:32 AM

Ajax UpdatePanel DropDownList auto-repeat problem.
 
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>
<asp:DropDownList ID="DropDownList1" runat="server"
AutoPostBack="true" OnDataBinding="DropDownList1_DataBinding"

OnSelectedIndexChanged="DropDownList1_SelectedInde xChanged" />
<br />
<asp:DropDownList ID="DropDownList2" runat="server"
AutoPostBack="true" OnDataBinding="DropDownList2_DataBinding" />
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
---8<---

bruce barker 09-25-2008 01:43 PM

Re: Ajax UpdatePanel DropDownList auto-repeat problem.
 
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>
> <asp:DropDownList ID="DropDownList1" runat="server"
> AutoPostBack="true" OnDataBinding="DropDownList1_DataBinding"
>
> OnSelectedIndexChanged="DropDownList1_SelectedInde xChanged" />
> <br />
> <asp:DropDownList ID="DropDownList2" runat="server"
> AutoPostBack="true" OnDataBinding="DropDownList2_DataBinding" />
> </ContentTemplate>
> </asp:UpdatePanel>
> </div>
> </form>
> </body>
> </html>
> ---8<---


cmeek1_1999 09-26-2008 06:51 AM

Re: Ajax UpdatePanel DropDownList auto-repeat problem.
 
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>
> > <asp:DropDownList ID="DropDownList1" runat="server"
> > AutoPostBack="true" OnDataBinding="DropDownList1_DataBinding"
> >
> > OnSelectedIndexChanged="DropDownList1_SelectedInde xChanged" />
> > <br />
> > <asp:DropDownList ID="DropDownList2" runat="server"
> > AutoPostBack="true" OnDataBinding="DropDownList2_DataBinding" />
> > </ContentTemplate>
> > </asp:UpdatePanel>
> > </div>
> > </form>
> > </body>
> > </html>
> > ---8<---

>


cmeek1_1999 09-27-2008 02:07 PM

Re: Ajax UpdatePanel DropDownList auto-repeat problem.
 
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<---



All times are GMT. The time now is 08:05 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.