我确信这很简单,但它让我疯了.
我的页面上有一个ListBox来显示艺术家,它们在索引被更改时调用一个方法,还有一个按钮,用于在单击时从另一个页面中加载该列表中的艺术家:
<asp:ListBox ID="lbArtists" runat="server" Rows="1" AutoPostBack="true" OnSelectedIndexChanged="ShowArtistsWorks" />
<asp:Button ID="btnEditArtist" runat="server" Text="Edit the artist" OnClick="LoadArtist" />
Run Code Online (Sandbox Code Playgroud)
接下来,我有一个类似的链接列表,它也有一个autopostback方法:
<asp:ListBox ID="lbLinks" runat="server" Rows="1" AutoPostBack="true" OnSelectedIndexChanged="LoadLink" />
Run Code Online (Sandbox Code Playgroud)
问题是,当我ShowArtistsWorks()通过单击调用时btnEditArtist,该LoadLink()方法也会被调用.为什么会这样?当我没有更改lbLinksListBox 上的索引时,为什么会调用它?它不应该接近那种方法.
编辑:(相关)代码隐藏方法(
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);
}
Run Code Online (Sandbox Code Playgroud)
编辑#2:我可以很容易地在个别方法中修复这个问题,以阻止它们发生,但是我想要理解为什么我不调用的方法,只能从一个地方调用,得到无意中援引.
接受的回答:尽管Boon(现在是CRice)首先得到了解释和解决方案,但我决定接受Jeff更彻底的解释,因为这是我想要的,更深入的分析.感谢所有回答的人.
更改事件在每次相关的回发时引发 - 如 MSDN 主题“ ASP.NET Web 服务器控件事件模型”中所述。
HTML 服务器控件和 Web 服务器控件(例如 TextBox 控件)中的更改事件不会立即导致发布。相反,它们会 在下次发帖时引发。
当用户单击“编辑艺术家”按钮时,ASP.NET 认为lbLinks.SelectedIndex已发生更改,因此它会调用其SelectedIndexChanged处理程序。
ASP.NET 认为索引已更改的原因是:当页面首次加载时,没有选定的索引(或值),除非您通过显式设置另有说明。lbLinks在执行此操作之前,所选索引为 -1,且其所选值为空字符串。呈现页面时,所选值(在本例中为空字符串)将写入视图状态,以便 ASP.NET 可以判断该值在回发时是否已更改。
您可以在调试时通过在渲染之前检查列表框的选定索引和值来观察这一点,或者您可以使用在线视图状态解码器之一(如这个)来查看页面第一次写入时的内容(尽管要阅读此内容) ,您需要了解序列化视图状态数据的结构)。
当您下次回发时,HTML<select>元素lbLinks 具有非空值,并且它作为发布数据的一部分提交。看一下Request.Form["lbLinks"],您会发现它等于lbLinks.Items[0].Value。
ASP.NET 将发布的值映射到lbLinks.SelectedValue,但它也知道所选值曾经是空字符串- 它从视图状态获取旧值。由于这两个值不同,该过程会引发控件的选定索引更改事件,从而导致您观察到的不良行为。
正如 boon 建议的那样,解决方案是在使用事件时始终SelectedIndex为所有控件显式设置,即使您只是将索引设置为零。ListBoxOnSelectedIndexChanged
(AutoPostBack 设置是一个不相关的转移注意力的内容。如果将其从两个列表框中删除,那么OnSelectedIndexChanged每次单击该按钮时,它们的事件都会触发。)