我确信这很简单,但它让我疯了。
我的页面上有一个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" />
此外,我有一个类似的链接列表,它也有一个autopostback方法:
<asp:ListBox ID="lbLinks" runat="server" Rows="1" AutoPostBack="true" OnSelectedIndexChanged="LoadLink" />
问题是,当我点击ShowArtistsWorks()
调用btnEditArtist
时,LoadLink()
方法也会被调用。为什么会这样?当我没有更改lbLinks
ListBox上的索引时,为什么会调用它?它不应该接近那种方法。
编辑:(相关)代码隐藏方法(
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);
}
编辑#2:我可以轻松地在个别方法中修复此问题以阻止它们发生,但是我不想理解为什么我不调用的方法,并且只能从一个地方调用,无意中被调用。
接受回答:尽管Boon(现在是CRice)首先得到解释和解决方案,但我决定接受Jeff更彻底的解释,因为这是我想要的,更深入的分析。感谢所有回答的人。
答案 0 :(得分:2)
如MSDN主题“ASP.NET Web Server Control Event Model”中所述,每次回发都会引发更改事件。{/ p>
更改HTML服务器控件中的事件 和Web服务器控件,如 TextBox控件,不要马上 引起一个帖子。相反,他们被提升 下次发布帖子时。
当用户单击“编辑艺术家”按钮时,ASP.NET认为lbLinks.SelectedIndex
已更改,因此它会调用其SelectedIndexChanged
处理程序。
原因 ASP.NET认为索引已更改为:当页面首次加载时,lbLinks
没有选定的索引(或值),除非您另有说明明确地设定它。在您执行此操作之前,所选索引为-1,其选定值为空字符串。在页面呈现时,所选值(在本例中为空字符串)将写入视图状态,以便ASP.NET可以判断回发值是否已更改。
您可以在调试时通过在渲染之前检查列表框的选定索引和值来观察此情况,或者您可以使用其中一个在线视图状态解码器(like this one)查看页面首次编写时的内容(虽然要阅读本文,但您需要了解the structure of serialized view state data)。
当您下次回发时,HTML <select>
元素lbLinks
具有非空值,并且它作为帖子数据的一部分提交。看看Request.Form["lbLinks"]
,您会发现它等于lbLinks.Items[0].Value
。
ASP.NET将发布的值映射到lbLinks.SelectedValue
,但它也知道所选的值曾经是一个空字符串 - 它从视图状态获取旧值。由于这两个值不同,因此该过程会引发控件的选定索引更改事件,从而导致您观察到的不良行为。
As boon suggested,解决方案是在您使用SelectedIndex
事件时始终为所有ListBox
控件明确设置OnSelectedIndexChanged
,即使您只是将索引设置为零。
(AutoPostBack设置是一个不相关的红色鲱鱼。如果您从两个列表框中删除它,每次单击按钮时它们的OnSelectedIndexChanged
事件都会触发。)
答案 1 :(得分:1)
根据该页面,两个列表框都已更改。它是selectedIndex -1,然后当页面加载时,它们都将转到选定的索引0,这可能是由于您为它们分配数据的方式。因此,当发生回发时,只有两个方法运行才有意义,因为它们的选定索引实际上已经改变了。
查看以下内容是否会使您的问题消失。将所选索引设置为零:
if (!IsPostBack){
GetArtists(); // populates artists listbox
GetLinks(); // populates links listbox
lbArtists.SelectedIndex = 0;
lbLinks.SelectedIndex = 0;
}
答案 2 :(得分:0)
您确定没有更改其他列表框中的索引吗?您是否重新绑定该列表框,因为该代码在post-pack上执行?
答案 3 :(得分:0)
我猜你在Page_Load()或其他类似的事件中调用了LoadLinks()。请记住,当您进行回发时,它必须重新运行整个页面生命周期。您正在使用页面类的全新实例。即使您只想处理简单的按钮点击或选择更改事件,也是如此。
答案 4 :(得分:0)
尝试查看调用堆栈&amp;看看为什么要调用不相关的方法。
我猜测它可能是改变其他列表框的Index
属性的代码。然后在那之后连接事件处理程序。
调用堆栈应该帮助您确定原因,一开始。
答案 5 :(得分:0)
问题在于你的AutoPostBack =“true”声明。我不知道其他人想要详细说明的确切原因,但是当页面上的多个控件具有AutoPostBack =“true”时,所有服务器端事件在发回服务器时都会被触发。
编辑我的猜测是,出于某种原因,可能与视图状态相关,对于回发的两个控件,SelectedIndexChanged正在评估为真。
答案 6 :(得分:0)
我的想法是第二个列表框不以选定的项目开头。页面加载时,您的浏览器会自动选择第一个项目。发布页面时,视图状态已更改(没有项目到第一项),因此发生回发事件。尽量确保你有一个选择。