English 中文(简体)
Why do unrelated (autopostback) methods get called when an Asp.Net ListBox autopostback method is invoked?
原标题:

I m sure this is simple but it s driving me nuts.

I have a ListBox on my page to show artists, which calls a method when the index is changed, and a button which loads an artist from that list in another page when clicked:

<asp:ListBox ID="lbArtists" runat="server" Rows="1" AutoPostBack="true" OnSelectedIndexChanged="ShowArtistsWorks" />

<asp:Button ID="btnEditArtist" runat="server" Text="Edit the artist" OnClick="LoadArtist" />

Further on, I have a similar list of links, which also has an autopostback method:

<asp:ListBox ID="lbLinks" runat="server" Rows="1" AutoPostBack="true" OnSelectedIndexChanged="LoadLink" />

The problem is, when I invoke ShowArtistsWorks() by clicking btnEditArtist, the LoadLink() method also gets called. Why is that happening? Why would that get called when I haven t changed the index on the lbLinks ListBox? It shouldn t be going near that method.

EDIT: (relevant) Code-behind methods (

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack){
        GetArtists(); // populates artists listbox
        GetLinks(); // populates links listbox
    }
}

protected void LoadArtist(object sender, EventArgs e){
    if (lbArtists.SelectedValue != "")
        Response.Redirect("Artist.aspx?id=" + lbArtists.SelectedValue);
}

protected void LoadLink(object sender, EventArgs e)
{
    if (lbLinks.SelectedValue != "")
        Response.Redirect("Link.aspx?id=" + lbLinks.SelectedValue);
}

EDIT #2: I could easily kludge a fix for this in the individual methods to stop them happening when they shouldn t, but I want to understand why methods that I don t call, and that only get called from one place, get invoked inadvertently.

ACCEPTED ANSWER: Even though Boon (now CRice) got in first with an explanation and a solution, I decided to accept Jeff s more thorough explanation because that was what I wanted, a more in-depth analysis. Thanks to everyone who answered.

最佳回答

Change events are raised on every postback for which they re relevant - as described in the MSDN topic "ASP.NET Web Server Control Event Model."

Change events in HTML server controls and Web server controls, such as the TextBox control, do not immediately cause a post. Instead, they are raised the next time a post occurs.

When users click your Edit Artist button, ASP.NET thinks lbLinks.SelectedIndex has changed, so it invokes its SelectedIndexChanged handler.

The reason ASP.NET thinks the index has changed is this: when the page first loads, lbLinks doesn t have a selected index (or value) unless you say otherwise by explicitly setting it. Until you do that, the selected index is -1 and its selected value is an empty string. The selected value (in this case, an empty string) is written to view state when the page is rendered so that ASP.NET can tell if the value has changed on postbacks.

You can observe this while debugging by inspecting your list boxes selected indices and values before rendering, or you can use one of the online view state decoders (like this one) to see what s in your page when it s first written (though to read this, you need to know about the structure of serialized view state data).

When you next post back, the HTML <select> element lbLinks has a non-empty value, and it is submitted as part of the post data. Take a look at Request.Form["lbLinks"] and you ll see that it equals lbLinks.Items[0].Value.

ASP.NET maps the posted value to lbLinks.SelectedValue, but it also knows that the selected value used to be an empty string - it gets the old value from view state. Since the two values are different, the process raises the control s selected index changed event, causing the undesirable behavior you ve observed.

As boon suggested, the solution is to always explicitly set the SelectedIndex for all your ListBox controls when you re using the OnSelectedIndexChanged event, even if you re just setting the index to zero.

(The AutoPostBack setting is an unrelated red herring. If you remove it from both list boxes, their OnSelectedIndexChanged events will both fire every time you click the button.)

问题回答

According to the page, both listboxes have changed. It was selectedIndex -1, then when the page loads they will both go to selected index 0, possibly due to the manner in which you are assigning data to them. So when a postback occurs it only makes sense for both of the methods to run since their selected index has actually changed.

See if the following makes your problem go away. Set the selected index as zero:

if (!IsPostBack){  
    GetArtists(); // populates artists listbox  
    GetLinks(); // populates links listbox

    lbArtists.SelectedIndex = 0;
    lbLinks.SelectedIndex = 0;
} 

Are you sure you haven t changed the index on the other listbox? Are you re-binding that list box, maybe, because that code get executed on post-pack?

I m guessing you call LoadLinks() in your Page_Load() or other similar event. Remember, when you do a postback, it has to re-run the entire page lifecycle. You re working with a brand new instance of the page class. This is true even if you just wanted to process a simple button click or selection change event.

Try seeing the call stack & see why the unrelated method is being called.

I am guessing that it could be the code that changes the Index property of the other listbox & then wiring of eventhandlers after that.

Call stack should help you identify the reason, to begin with.

The problem is in your AutoPostBack="true" declarations. I don t know the exact reason if anyone else would like to elaborate, but when multiple controls on a page have AutoPostBack="true", all server side events are fired when posting back to the server.

EDIT My guess is that for some reason, possibly related to view state the SelectedIndexChanged is evaluating to true for both controls on postback.

My thought is that the second list box doesn t start with a selected item. When the page loads, your browser is selecting the first item automatically. When you post the page, the viewstate has changed (no item to first item) so the postback event occurs. Try making sure you ve got a selection.





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Transaction handling with TransactionScope

I am implementing Transaction using TransactionScope with the help this MSDN article http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx I just want to confirm that is ...

System.Web.Mvc.Controller Initialize

i have the following base controller... public class BaseController : Controller { protected override void Initialize(System.Web.Routing.RequestContext requestContext) { if (...

Microsoft.Contracts namespace

For what it is necessary Microsoft.Contracts namespace in asp.net? I mean, in what cases I could write using Microsoft.Contracts;?

Separator line in ASP.NET

I d like to add a simple separator line in an aspx web form. Does anyone know how? It sounds easy enough, but still I can t manage to find how to do it.. 10x!

热门标签