简体   繁体   中英

Dropdownlist SelectedIndexChanged firing on every postback

I am dynamically adding a custom user control to an update panel. My user control contains two dropdownlists and a textbox. When a control outside of the update panel triggers a postsback, I am re-adding the user control to the update panel.

The problem is...on postback when I re-add the user controls, it's firing the "SelectedIndexChanged" event of the dropdownlists inside the user control. Even if the selectedindex did not change since the last postback.

Any ideas?

I can post the code if necessary, but there's quite a bit in this particular scenario.

Thanks in advance!

EDIT...CODE ADDED BELOW

* .ASCX

<asp:DropDownList ID="ddlColumns" OnSelectedIndexChanged="ddlColumns_SelectedChanged" AppendDataBoundItems="true" AutoPostBack="true" runat="server">

* .ASCX.CS

List<dataColumnSpecs> dataColumns = new List<dataColumnSpecs>();

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

public void fillDataColumnsList()
{
    dataColumns.Clear();
    //COMMON GETDATATABLE RETURNS A DATA TABLE POPULATED WITH THE RESULTS FROM THE STORED PROC COMMAND
    DataTable dt = common.getDataTable(storedProcs.SELECT_COLUMNS, new List<SqlParameter>());
    foreach (DataRow dr in dt.Rows)
    {
        dataColumns.Add(new dataColumnSpecs(dr["columnName"].ToString(), dr["friendlyName"].ToString(), dr["dataType"].ToString(), (int)dr["dataSize"]));
    }
}

public void fillDDLColumns()
{
    fillDataColumnsList();
    ddlColumns.Items.Clear();
    foreach (dataColumnSpecs dcs in dataColumns) 
    { 
        ListItem li = new ListItem(); 
        li.Text = dcs.friendlyName; 
        li.Value = dcs.columnName; 
        ddlColumns.Items.Add(li);
    }
    ddlColumns.Items.Insert(0, new ListItem(" -SELECT A COLUMN- ", ""));
    ddlColumns.DataBind();  
}

protected void ddlColumns_SelectedChanged(object sender, EventArgs e)
{
    //THIS CODE IS BEING FIRED WHEN A BUTTON ON THE PARENT *.ASPX IS CLICKED
}

* .ASPX

<asp:UpdatePanel ID="upControls" runat="server">
    <ContentTemplate>
        <asp:Button ID="btnAddControl" runat="server" Text="+" OnClick="btnAddControl_Click" />
    </ContentTemplate>
</asp:UpdatePanel>
<asp:Button ID="btnGo" runat="server" Text="Go" OnClick="btnGo_Click" ValidationGroup="vgGo" />
<asp:GridView...

* .ASPX.CS

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        uc_Counter = 0;
        addControl();
        gridview_DataBind();
    }
    else
    {
        reloadControls();
    }
}

protected void btnGo_Click(object sender, EventArgs e)
{
    if (Page.IsValid)
    {
        //THIS BUTTON CLICK IS WHAT'S TRIGGERING THE 
        //SELECTEDINDEXCHANGED EVENT TO FIRE ON MY *.ASCX
        gridview_DataBind();
    }   
}

private void reloadControls()
{
    int count = this.uc_Counter;

    for (int i = 0; i < count; i++)
    {
        Control myUserControl = Page.LoadControl("~/Controls/myUserControl.ascx");
        myUserControl.ID = "scID_" + i;
        upControls.ContentTemplateContainer.Controls.AddAt(i, myUserControl);
        ((customUserControl)myUserControl).fillDDLColumns();
    }
}

private void addControl()
{
    Control myUserControl = Page.LoadControl("~/Controls/myUserControl.ascx");
    myUserControl.ID = "scID_" + uc_Counter.ToString();
    upControls.ContentTemplateContainer.Controls.AddAt(upControls.ContentTemplateContainer.Controls.IndexOf(btnAddControl), myUserControl);            
    //((customUserControl)myUserControl).fillDDLColumns();
    this.uc_Counter++;
}

protected int uc_Counter
{
    get { return (int)ViewState["uc_Counter"]; }
    set { ViewState["uc_Counter"] = value; }
}

Even though this is already answered I want to put an answer here since I've recently tangled with this problem and I couldn't find an answer anywhere that helped me but I did find a solution after a lot of digging into the code.

For me, the reason why this was happening was due to someone overwriting PageStatePersister to change how the viewstate hidden field is rendered. Why do that? I found my answer here .

One of the greatest problems when trying to optimize an ASP.NET page to be more search engine friendly is the view state hidden field. Most search engines give more score to the content of the firsts[sic] thousands of bytes of the document so if your first 2 KB are view state junk your pages are penalized. So the goal here is to move the view state data as down as possible.

What the code I encountered did was blank out the __VIEWSTATE hidden fields and create a view_state hidden field towards the bottom of the page. The problem with this is that it totally mucked up the viewstate and I was getting dropdownlists reported as being changed when they weren't, as well as having all dropdownlists going through the same handler on submit. It was a mess. My solution was to turn off this custom persister on this page only so I wouldn't have to compensate for all this weirdness.

protected override PageStatePersister PageStatePersister
{
    get
    {
        if (LoginRedirectUrl == "/the_page_in_question.aspx")
        {
            return new HiddenFieldPageStatePersister(Page);
        }
        return new CustomPageStatePersister(this);
    }
}

This allowed me to have my proper viewstate for the page I needed it on but kept the SEO code for the rest of the site. Hope this helps someone.

I found my answer in this post .net DropDownList gets cleared after postback

I changed my counter that I was storing in the viewstate to a session variable. Then I moved my reloadControls() function from the Page_Load of the *.ASPX to the Page_Init.

The key was dynamically adding my user control in the Page_Init so it would be a member of the page before the Viewstate was applied to controls on the page.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM