最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - __doPostBack only works if there is a LinkButton, Calendar or WizardStep control on the page - Stack Overflow

programmeradmin8浏览0评论

I have identified a problem with __doPostBack and found a work around. I am seeking an explanation for the cause and/or a better solution than my work around.

Scenario: I have a dropdown populated with the values; "-Select-", "One" & "Two". If the user selects "One" than client side script is executed. If the user selects "Two" than server side script is executed.

Problem: The client script initiates the postback by calling __doPostBack. However, no post back actually occurs unless there is also a LinkButton, Calendar or WizardStep control on the page. I actually went through all of the standard tools in the Visual Studio Toolbox and tested them all. It has to be one of those three.

Work Around: Add a link button surrounded by a span with display set to none.

<span style="display:none;">
    <asp:LinkButton ID="LinkButton1" runat="server">LinkButton</asp:LinkButton>
</span>

Question: Can somebody provide an explanation for this behavior or provide a better fix than my "Work Around"?

Source - Javascript (I placed it between the head tags)

<script language="javascript" type="text/javascript">
    function DropDownList1_change(elementRef) {
        var selectedIndex = elementRef.selectedIndex;
        if (selectedIndex > 0) {
            var selectedValue = elementRef.options[selectedIndex].value;
            if (selectedValue == "One") {
                alert("Because you selected 'One', special javascript code will be executed");
                // Special javascript code goes here
                return;
            }
            else if (selectedValue == "Two") {
                // Special server code gets executed on server DropDownList1_SelectedIndexChanged
                __doPostBack('DropDownList1', '');
            }
        }
    }
</script>

Source - ASPX Controls

    <asp:DropDownList ID="DropDownList1" runat="server"  onchange="DropDownList1_change(this)" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
        <asp:ListItem>-Select-</asp:ListItem>
        <asp:ListItem>One</asp:ListItem>
        <asp:ListItem>Two</asp:ListItem>
    </asp:DropDownList>
    <br />

    <!-- For some unknown reason __doPostBack only works if there is a LinkButton, Calendar or WizardStep control on the page -->      
    <span style="display:none;">
        <asp:LinkButton ID="LinkButton1" runat="server">LinkButton</asp:LinkButton>
    </span>

    Time of last Post Back: <asp:Label ID="Label1" runat="server"></asp:Label><br />
    Time of OnSelectedIndexChanged: <asp:Label ID="Label2" runat="server"></asp:Label>

Source - Code Behind

    protected void Page_Load(object sender, EventArgs e)
    {
        Label1.Text = DateTime.Now.ToLongTimeString();
    }

    protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
    {
        Label2.Text = DateTime.Now.ToLongTimeString();
    }

Additional Resource - I found the following article after posting this question. Its a very old Microsoft article and the only Microsoft article I found that mentions the specific limitation of DropDowns, return values & postbacks. I haven't digged deep into their solution and not sure time will allow me to. Mainly posting it in case my solution fails down the road or doesn't work for someone else.

Intuitively you might think adding a confirm dialog box for a DropDownList is identical to adding such a dialog box for a Button Web control. That is, simply set the DropDownList's client-side onchange attribute to something like: return confirm(...);. using: DropDownListID.Attributes("onchange") = "return confirm(...);" Unfortunately, this won't work as desired because an AutoPostBack DropDownList's onchange attribute will be set to a bit of JavaScript that causes a postback, namely a call to the client-side __doPostBack function. When setting the onchange attribute programmatically yourself, the end result is that the rendered client-side onchange event handler has both your code and the call to __doPostBack:

The article is long so search for "Confirmation with AutoPostBack DropDownLists"

.aspx

I have identified a problem with __doPostBack and found a work around. I am seeking an explanation for the cause and/or a better solution than my work around.

Scenario: I have a dropdown populated with the values; "-Select-", "One" & "Two". If the user selects "One" than client side script is executed. If the user selects "Two" than server side script is executed.

Problem: The client script initiates the postback by calling __doPostBack. However, no post back actually occurs unless there is also a LinkButton, Calendar or WizardStep control on the page. I actually went through all of the standard tools in the Visual Studio Toolbox and tested them all. It has to be one of those three.

Work Around: Add a link button surrounded by a span with display set to none.

<span style="display:none;">
    <asp:LinkButton ID="LinkButton1" runat="server">LinkButton</asp:LinkButton>
</span>

Question: Can somebody provide an explanation for this behavior or provide a better fix than my "Work Around"?

Source - Javascript (I placed it between the head tags)

<script language="javascript" type="text/javascript">
    function DropDownList1_change(elementRef) {
        var selectedIndex = elementRef.selectedIndex;
        if (selectedIndex > 0) {
            var selectedValue = elementRef.options[selectedIndex].value;
            if (selectedValue == "One") {
                alert("Because you selected 'One', special javascript code will be executed");
                // Special javascript code goes here
                return;
            }
            else if (selectedValue == "Two") {
                // Special server code gets executed on server DropDownList1_SelectedIndexChanged
                __doPostBack('DropDownList1', '');
            }
        }
    }
</script>

Source - ASPX Controls

    <asp:DropDownList ID="DropDownList1" runat="server"  onchange="DropDownList1_change(this)" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
        <asp:ListItem>-Select-</asp:ListItem>
        <asp:ListItem>One</asp:ListItem>
        <asp:ListItem>Two</asp:ListItem>
    </asp:DropDownList>
    <br />

    <!-- For some unknown reason __doPostBack only works if there is a LinkButton, Calendar or WizardStep control on the page -->      
    <span style="display:none;">
        <asp:LinkButton ID="LinkButton1" runat="server">LinkButton</asp:LinkButton>
    </span>

    Time of last Post Back: <asp:Label ID="Label1" runat="server"></asp:Label><br />
    Time of OnSelectedIndexChanged: <asp:Label ID="Label2" runat="server"></asp:Label>

Source - Code Behind

    protected void Page_Load(object sender, EventArgs e)
    {
        Label1.Text = DateTime.Now.ToLongTimeString();
    }

    protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
    {
        Label2.Text = DateTime.Now.ToLongTimeString();
    }

Additional Resource - I found the following article after posting this question. Its a very old Microsoft article and the only Microsoft article I found that mentions the specific limitation of DropDowns, return values & postbacks. I haven't digged deep into their solution and not sure time will allow me to. Mainly posting it in case my solution fails down the road or doesn't work for someone else.

Intuitively you might think adding a confirm dialog box for a DropDownList is identical to adding such a dialog box for a Button Web control. That is, simply set the DropDownList's client-side onchange attribute to something like: return confirm(...);. using: DropDownListID.Attributes("onchange") = "return confirm(...);" Unfortunately, this won't work as desired because an AutoPostBack DropDownList's onchange attribute will be set to a bit of JavaScript that causes a postback, namely a call to the client-side __doPostBack function. When setting the onchange attribute programmatically yourself, the end result is that the rendered client-side onchange event handler has both your code and the call to __doPostBack:

The article is long so search for "Confirmation with AutoPostBack DropDownLists"

https://msdn.microsoft./en-us/library/aa479302.aspx

Share Improve this question edited Aug 3, 2016 at 21:37 Dave asked Aug 3, 2016 at 17:38 DaveDave 6691 gold badge6 silver badges13 bronze badges 5
  • Honestly, the best workaround I've got is to not use WebForms. The technology is absolutely awful for doing anything custom in the browser, like what you're doing. If you use WebForms, then in my opinion you should do it 100%, which would mean instead of using onchange and executing traditional javascript, handle your One scenario inside the postback itself and potentially register custom javascript on the response of that postback. – Joe Enos Commented Aug 3, 2016 at 17:51
  • Do you observe that behavior in a new project? I tried reproducing the problem (with VS 2010 and .NET Framework 4.0) and the postback is performed every time by selecting an item in the DropDownList. – Martin Parenteau Commented Aug 3, 2016 at 18:50
  • I get the same behavior in a new project; I created both an empty new web site and web application project for testing it. I am using VS 2010, .NET Framework 4, windows 7 32 bit & Cassini (will try it from IIS). – Dave Commented Aug 3, 2016 at 19:05
  • Tried IIS instead of Cassini. Same issue. – Dave Commented Aug 3, 2016 at 19:28
  • __doPostBack is not supposed to be used directly by client scripts. This is why it has double underscore. Like private private. – Stilgar Commented Aug 4, 2016 at 12:10
Add a ment  | 

1 Answer 1

Reset to default 6

There are 2 solutions.

Solution 1: A better work around than adding a link button surrounded by hidden span tags is to add the following to the page load event. This ensures that the function __doPostBack is available.

protected void Page_Load(object sender, EventArgs e)
{
    Page.ClientScript.GetPostBackEventReference(this, string.Empty);
}

The function __doPostBack is generated only if a control in the form needs it to perform postbacks. This includes controls like the LinkButton and other controls for which AutoPostBack is set to true. In fact, only the Button and ImageButton controls can perform postbacks without __doPostBack (see this article). For example, we can see in the HTML output that a LinkButton is rendered this way:

<a id="lnk" href="javascript:__doPostBack(&#39;lnk&#39;,&#39;&#39;)">My link</a>


Solution 2: The following approach achieves the same thing without using __doPostBack.

In the present case, you could set AutoPostBack="true" for the DropDownList:

<asp:DropDownList AutoPostBack="true" onchange="if (!confirmPostBack(this)) return false;" ... >

The onchange event handler would return false when you want to prevent the postback. The Javascript function could be something like this:

function confirmPostBack(ddl)
{
    if (condition) {
        ...
        return true;
    } 
    else {
        ...
        return false;
    }
}

Important: The onchange event handler should not return anything to allow the postback to occur. You can use this syntax:

onchange="if (!confirmPostBack(this)) return false;"

For reasons probably explained in the article mentioned in the question, the following syntax does not work. Returning true still prevents the postback.

onchange="return confirmPostBack(this);" // Does not work!

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论