Ajax UpdatePanel DropDownList auto-repeat problem.

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • =?Utf-8?B?Y21lZWsxXzE5OTk=?=

    Ajax UpdatePanel DropDownList auto-repeat problem.

    Hello,

    On a webpage, create an UpdatePanel with two DropDownLists.
    Set AutoPostBack of DropDownList1 to true.
    In the SelectedIndexCh anged 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.W ebControls;

    namespace AjaxDdlTest
    {
    public partial class _Default : System.Web.UI.P age
    {
    protected void Page_Load(objec t sender, EventArgs e)
    {
    if (!IsPostBack)
    {
    DropDownList1.D ataBind(); //breakpoint here
    DropDownList1.S electedValue = "0";
    DropDownList2.D ataBind();
    DropDownList1.F ocus();
    }
    }

    protected void DropDownList1_S electedIndexCha nged(object sender,
    EventArgs e)
    {
    DropDownList ddl = (DropDownList)s ender;
    DropDownList2.D ataBind();
    ScriptManager1. SetFocus(ddl);
    }

    protected void DropDownList1_D ataBinding(obje ct sender, EventArgs e)
    {
    DropDownList ddl = (DropDownList)s ender;
    ddl.Items.Clear ();
    for (int i = 0; i < 200; i++)
    {
    ddl.Items.Add(i .ToString());
    }
    }

    protected void DropDownList2_D ataBinding(obje ct sender, EventArgs e)
    {
    DropDownList ddl = (DropDownList)s ender;
    ddl.Items.Clear ();
    for (int i = int.Parse(DropD ownList1.Select edValue); i < 200; i++)
    {
    ddl.Items.Add(i .ToString());
    }
    }
    }
    }
    ---8<---
    default.aspx
    ---8<---
    <%@ Page Language="C#" AutoEventWireup ="true" Codebehind="Def ault.aspx.cs"
    Inherits="AjaxD dlTest._Default " %>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dt d">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
    <title>Untitl ed Page</title>
    </head>
    <body>
    <form id="form1" runat="server">
    <asp:ScriptMana ger ID="ScriptManag er1" runat="server" />
    <div>
    <asp:UpdatePane l ID="UpdatePanel 1" runat="server">
    <ContentTemplat e>
    <asp:DropDownLi st ID="DropDownLis t1" runat="server"
    AutoPostBack="t rue" OnDataBinding=" DropDownList1_D ataBinding"

    OnSelectedIndex Changed="DropDo wnList1_Selecte dIndexChanged" />
    <br />
    <asp:DropDownLi st ID="DropDownLis t2" runat="server"
    AutoPostBack="t rue" OnDataBinding=" DropDownList2_D ataBinding" />
    </ContentTemplate >
    </asp:UpdatePanel >
    </div>
    </form>
    </body>
    </html>
    ---8<---
  • bruce barker

    #2
    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 SelectedIndexCh anged 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.W ebControls;
    >
    namespace AjaxDdlTest
    {
    public partial class _Default : System.Web.UI.P age
    {
    protected void Page_Load(objec t sender, EventArgs e)
    {
    if (!IsPostBack)
    {
    DropDownList1.D ataBind(); //breakpoint here
    DropDownList1.S electedValue = "0";
    DropDownList2.D ataBind();
    DropDownList1.F ocus();
    }
    }
    >
    protected void DropDownList1_S electedIndexCha nged(object sender,
    EventArgs e)
    {
    DropDownList ddl = (DropDownList)s ender;
    DropDownList2.D ataBind();
    ScriptManager1. SetFocus(ddl);
    }
    >
    protected void DropDownList1_D ataBinding(obje ct sender, EventArgs e)
    {
    DropDownList ddl = (DropDownList)s ender;
    ddl.Items.Clear ();
    for (int i = 0; i < 200; i++)
    {
    ddl.Items.Add(i .ToString());
    }
    }
    >
    protected void DropDownList2_D ataBinding(obje ct sender, EventArgs e)
    {
    DropDownList ddl = (DropDownList)s ender;
    ddl.Items.Clear ();
    for (int i = int.Parse(DropD ownList1.Select edValue); i < 200; i++)
    {
    ddl.Items.Add(i .ToString());
    }
    }
    }
    }
    ---8<---
    default.aspx
    ---8<---
    <%@ Page Language="C#" AutoEventWireup ="true" Codebehind="Def ault.aspx.cs"
    Inherits="AjaxD dlTest._Default " %>
    >
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dt d">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
    <title>Untitl ed Page</title>
    </head>
    <body>
    <form id="form1" runat="server">
    <asp:ScriptMana ger ID="ScriptManag er1" runat="server" />
    <div>
    <asp:UpdatePane l ID="UpdatePanel 1" runat="server">
    <ContentTemplat e>
    <asp:DropDownLi st ID="DropDownLis t1" runat="server"
    AutoPostBack="t rue" OnDataBinding=" DropDownList1_D ataBinding"
    >
    OnSelectedIndex Changed="DropDo wnList1_Selecte dIndexChanged" />
    <br />
    <asp:DropDownLi st ID="DropDownLis t2" runat="server"
    AutoPostBack="t rue" OnDataBinding=" DropDownList2_D ataBinding" />
    </ContentTemplate >
    </asp:UpdatePanel >
    </div>
    </form>
    </body>
    </html>
    ---8<---

    Comment

    • =?Utf-8?B?Y21lZWsxXzE5OTk=?=

      #3
      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(objec t sender, EventArgs e)
      {
      if (!IsPostBack)
      {
      string ddl_timeout_id = DropDownList1.C lientID + "_timeoutId ";
      string ddl_submit = DropDownList1.C lientID + "_submit";
      string delayscript =
      @"var " + ddl_timeout_id + @"=0;
      function " + ddl_submit + @"()
      {
      clearTimeout(" + ddl_timeout_id + @");
      " + ddl_timeout_id + @"=setTimeout(' " +
      ClientScript.Ge tPostBackEventR eference(DropDo wnList1,
      string.Empty).R eplace(@"'", @"\'")
      + @"', 500);
      return true;
      }";
      ClientScript.Re gisterClientScr iptBlock(typeof (_Default),
      ddl_submit, delayscript, true);
      DropDownList1.D ataBind(); //breakpoint here
      DropDownList1.A ttributes["onchange"] = @"return " +
      ddl_submit + @"();alert('Bug :No return');";
      DropDownList1.S electedValue = "0";
      DropDownList2.D ataBind();
      DropDownList1.F ocus();
      }
      }


      "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 SelectedIndexCh anged 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.W ebControls;

      namespace AjaxDdlTest
      {
      public partial class _Default : System.Web.UI.P age
      {
      protected void Page_Load(objec t sender, EventArgs e)
      {
      if (!IsPostBack)
      {
      DropDownList1.D ataBind(); //breakpoint here
      DropDownList1.S electedValue = "0";
      DropDownList2.D ataBind();
      DropDownList1.F ocus();
      }
      }

      protected void DropDownList1_S electedIndexCha nged(object sender,
      EventArgs e)
      {
      DropDownList ddl = (DropDownList)s ender;
      DropDownList2.D ataBind();
      ScriptManager1. SetFocus(ddl);
      }

      protected void DropDownList1_D ataBinding(obje ct sender, EventArgs e)
      {
      DropDownList ddl = (DropDownList)s ender;
      ddl.Items.Clear ();
      for (int i = 0; i < 200; i++)
      {
      ddl.Items.Add(i .ToString());
      }
      }

      protected void DropDownList2_D ataBinding(obje ct sender, EventArgs e)
      {
      DropDownList ddl = (DropDownList)s ender;
      ddl.Items.Clear ();
      for (int i = int.Parse(DropD ownList1.Select edValue); i < 200; i++)
      {
      ddl.Items.Add(i .ToString());
      }
      }
      }
      }
      ---8<---
      default.aspx
      ---8<---
      <%@ Page Language="C#" AutoEventWireup ="true" Codebehind="Def ault.aspx.cs"
      Inherits="AjaxD dlTest._Default " %>

      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dt d">
      <html xmlns="http://www.w3.org/1999/xhtml">
      <head runat="server">
      <title>Untitl ed Page</title>
      </head>
      <body>
      <form id="form1" runat="server">
      <asp:ScriptMana ger ID="ScriptManag er1" runat="server" />
      <div>
      <asp:UpdatePane l ID="UpdatePanel 1" runat="server">
      <ContentTemplat e>
      <asp:DropDownLi st ID="DropDownLis t1" runat="server"
      AutoPostBack="t rue" OnDataBinding=" DropDownList1_D ataBinding"

      OnSelectedIndex Changed="DropDo wnList1_Selecte dIndexChanged" />
      <br />
      <asp:DropDownLi st ID="DropDownLis t2" runat="server"
      AutoPostBack="t rue" OnDataBinding=" DropDownList2_D ataBinding" />
      </ContentTemplate >
      </asp:UpdatePanel >
      </div>
      </form>
      </body>
      </html>
      ---8<---
      >

      Comment

      • =?Utf-8?B?Y21lZWsxXzE5OTk=?=

        #4
        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 AutoPostBackDel ayBehavior.js an embedded resource and let
        the ClientScriptRes ource attribute point to the right place.
        Let the TargetControlId be the Id of the DropDownList, and it seems to work.

        Thanks again.

        Carlo Mekenkamp

        AutoPostBackDel ayExtender.cs
        ---8<---
        using System;
        using System.Web.UI.W ebControls;
        using System.Web.UI;
        using System.Componen tModel;
        using System.Componen tModel.Design;
        using AjaxControlTool kit;

        [assembly:
        System.Web.UI.W ebResource("Aut oPostBackDelay. AutoPostBackDel ayBehavior.js",
        "text/javascript")]

        namespace AutoPostBackDel ay
        {
        [Designer(typeof (AutoPostBackDe layDesigner))]
        [ClientScriptRes ource("AutoPost BackDelay.AutoP ostBackDelayBeh avior",
        "AutoPostBackDe lay.AutoPostBac kDelayBehavior. js")]
        [TargetControlTy pe(typeof(Contr ol))]
        public class AutoPostBackDel ayExtender : ExtenderControl Base
        {
        // TODO: Add your property accessors here.
        //
        [ExtenderControl Property]
        [DefaultValue(50 0)]
        public int DelayTime
        {
        get
        {
        return GetPropertyValu e("DelayTime" , 500);
        }
        set
        {
        SetPropertyValu e("DelayTime" , value);
        }
        }
        [ExtenderControl Property]
        [DefaultValue(60 0)]
        public int ResetTime
        {
        get
        {
        return GetPropertyValu e("ResetTime" , 600);
        }
        set
        {
        SetPropertyValu e("ResetTime" , value);
        }
        }

        /// <summary>
        /// Specifies the script to run to initiate a postback
        /// </summary>
        [ExtenderControl Property]
        [ClientPropertyN ame("postBackSc ript")]
        [DefaultValue("" )]
        [Browsable(false )]
        [EditorBrowsable (EditorBrowsabl eState.Never)]
        public string PostBackScript
        {
        get
        {
        return GetPropertyValu e("PostBackScri pt", string.Empty);
        }
        set
        {
        SetPropertyValu e("PostBackScri pt", value);
        }
        }

        protected override void OnLoad(EventArg s e)
        {
        base.OnLoad(e);
        PostBackScript =
        Page.ClientScri pt.GetPostBackE ventReference(T argetControl, "");
        }
        }
        }
        ---8<---
        AutoPostBackDel ayDesigner.cs
        ---8<---
        using System.Web.UI.W ebControls;
        using System.Web.UI;

        namespace AutoPostBackDel ay
        {
        class AutoPostBackDel ayDesigner :
        AjaxControlTool kit.Design.Exte nderControlBase Designer<AutoPo stBackDelayExte nder>
        {


        }
        }
        ---8<---
        AutoPostBackDel ayBehavior.js
        ---8<---
        Type.registerNa mespace('AutoPo stBackDelay');

        AutoPostBackDel ay.AutoPostBack DelayBehavior = function(elemen t) {
        AutoPostBackDel ay.AutoPostBack DelayBehavior.i nitializeBase(t his,
        [element]);

        // TODO : (Step 1) Add your property variables here
        this._DelayTime Value = 500;
        this._ResetTime Value = 600;
        this._CurrentDe layTimeValue = 0;
        this._DelayId = 0;
        this._ResetId = 0;
        // Script to call to initiate a postback
        this._postBackS cript = null;
        this._changeHan dler = null;
        this._oldScript = null;
        }
        AutoPostBackDel ay.AutoPostBack DelayBehavior.p rototype = {
        initialize : function() {
        AutoPostBackDel ay.AutoPostBack DelayBehavior.c allBaseMethod(t his,
        'initialize');

        var element = this.get_elemen t();

        // Attach the handler
        this._changeHan dler = Function.create Delegate(this, this._onChange) ;
        $addHandler(ele ment, "change", this._changeHan dler);

        this._oldScript = element.getAttr ibute("onchange ");
        if (this._oldScrip t) {
        element.setAttr ibute("onchange ", null);
        }
        // TODO: Add your initalization code here
        },

        dispose : function() {
        // TODO: Add your cleanup code here
        clearTimeout(th is._ResetId);
        clearTimeout(th is._DelayId);
        this._CurrentDe layTimeValue = 0;
        // Detach event handlers
        if (this._changeHa ndler) {
        $removeHandler( this.get_elemen t(), "change", this._changeHan dler);
        this._changeHan dler = null;
        }

        if (this._oldScrip t) {
        this.get_elemen t().setAttribut e("onchange", this._oldScript );
        this._oldScript = null;
        }

        AutoPostBackDel ay.AutoPostBack DelayBehavior.c allBaseMethod(t his,
        'dispose');
        },

        // TODO: (Step 2) Add your property accessors here
        _onChange : function() {
        var e = this.get_elemen t();
        if (e) {
        clearTimeout(th is._ResetId);
        clearTimeout(th is._DelayId);
        this._DelayId = setTimeout(Func tion.createDele gate(this,
        this._postBack) , this._CurrentDe layTimeValue);
        this._ResetId = setTimeout(Func tion.createDele gate(this,
        this._reset), this._ResetTime Value);
        this._CurrentDe layTimeValue = this._DelayTime Value;
        return false;
        }
        },

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

        _postBack : function() {
        if (this._postBack Script) {
        eval(this._post BackScript);
        }
        },

        get_postBackScr ipt : function() {
        /// <value type="String">
        /// Script to run to initiate a postback
        /// </value>
        return this._postBackS cript;
        },
        set_postBackScr ipt : function(value) {
        if (this._postBack Script != value) {
        this._postBackS cript = value;
        this.raisePrope rtyChanged('pos tBackScript');
        }
        },

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

        get_ResetTime : function() {
        return this._ResetTime Value;
        },
        set_ResetTime : function(value) {
        this._ResetTime Value = value;
        }
        }
        AutoPostBackDel ay.AutoPostBack DelayBehavior.r egisterClass('A utoPostBackDela y.AutoPostBackD elayBehavior', AjaxControlTool kit.BehaviorBas e);
        ---8<---

        Comment

        Working...