Robin Day
Robin Day

Reputation: 102478

RadioButtonList set in PreLoad causes UpdatePanel Trigger to not fire when set back to initial value

We had some "strange" issues when using UpdatePanels and RadioButtonLists in that a PostBack was not occuring when you changed the values.

I've managed to track down the issue in that it occurs when the value of the RadioButtonList is set in the PreLoad of a page and you are re-selecting this initial value.

I have the full code of the ASP page and the CodeBehind below.

ASPX:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="RBLPostBackIssue._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"></asp:ScriptManager>
    <div>
    <asp:Label ID="Label1" runat="server"></asp:Label>
    <asp:RadioButtonList ID="RadioButtonList1" AutoPostBack="true" OnSelectedIndexChanged="RadioButtonList1_SelectedIndexChanged" RepeatDirection="Horizontal" runat="server">
        <asp:ListItem>Yes</asp:ListItem>
        <asp:ListItem>No</asp:ListItem>
    </asp:RadioButtonList>
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
            <asp:PlaceHolder ID="PlaceHolder1" runat="server">
                <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
            </asp:PlaceHolder>
        </ContentTemplate>
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="RadioButtonList1" EventName="SelectedIndexChanged" />
        </Triggers>
    </asp:UpdatePanel>
    </div>
    </form>
</body>
</html>

CodeBehind:

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace RBLPostBackIssue
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_PreLoad(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                switch (new Random().Next(2))
                {
                    case 0:
                        Label1.Text = "Initial value set to Yes";
                        RadioButtonList1.SelectedValue = "Yes";
                        break;
                    case 1:
                        Label1.Text = "Initial value set to No";
                        RadioButtonList1.SelectedValue = "No";
                        break;
                }
            }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                ShowHideLogic();
            }
        }

        private void ShowHideLogic()
        {
            PlaceHolder1.Visible = RadioButtonList1.SelectedValue.ToLower().Contains("yes");
        }

        protected void RadioButtonList1_SelectedIndexChanged(object sender, EventArgs e)
        {
            ShowHideLogic();
        }
    }
}

The following occurs.

The setting of the inital value in the PreLoad comes from some legacy code that we would prefer not to change. Any change there will require a substantial amount of testing and re-deploying to a large number of other projects.

The only solution I have found is to not use a Trigger for the RadioButtonList but to put it within the UpdatePanel. Whislt this is a solution in some cases, it is not ideal as UI does not allways allow this.

I guess my question is, has anyone else had this problem, do you know of another solution to it, or am I just being stupid and have missed something obvious?

Upvotes: 1

Views: 3386

Answers (1)

Graham Clark
Graham Clark

Reputation: 12966

This is down to how ASP.Net renders the HTML for the radio button list. If you view the source of the page when it's first loaded, the <input> element that's initially selected will have a checked="checked" attribute. The <input> element that isn't initially selected will instead have a onclick="javascript:setTimeout('__doPostBack...')" attribute.

So, a postback will only occur if you change the selected item, fair enough.

However, as you're using an UpdatePanel, the whole page isn't being re-rendered on post-back, just the contents of the update panel. So, if Yes is initially selected, clicking No will post back and the text box will be removed. But the HTML for the radio buttons hasn't changed, so clicking Yes now will not post back, as there's no javascript to do this.

You can fix all this by either putting the radio button list in the same UpdatePanel as the PlaceHolder, or by putting the radio button list in its own UpdatePanel. This will ensure the HTML that renders the radio buttons will be updated after each post back, and things will work as expected.

Upvotes: 3

Related Questions