在回发期间,selectedIndex丢失了 – ASP.NET

我有一个列表框控件:

 

背后的代码类似于:

private void Page_Load(object sender, System.EventArgs e) { lbox.SelectedIndexChanged+=new EventHandler(lbox_SelectedIndexChanged); if(!Page.IsPostBack) { LoadData(); } } private LoadData() { lbox.DataSource = foo(); lbox.DataBind(); } protected void lboxScorecard_SelectedIndexChanged(object sender, EventArgs e) { int index = (sender as ListBox).selectedIndex; }
private void Page_Load(object sender, System.EventArgs e) { lbox.SelectedIndexChanged+=new EventHandler(lbox_SelectedIndexChanged); if(!Page.IsPostBack) { LoadData(); } } private LoadData() { lbox.DataSource = foo(); lbox.DataBind(); } protected void lboxScorecard_SelectedIndexChanged(object sender, EventArgs e) { int index = (sender as ListBox).selectedIndex; } 

我的问题是,当我的页面收到回复post时(当用户在列表框中进行选择时),选择总是“跳转”到列表框中的第一个项目,因此我的回调函数中的索引变量始终为0。

这似乎可能是一个viewstate问题? 如何修复它以便选择索引保留在回发中?

没有ajax,这是.NET 1.0。

谢谢。

编辑1 JohnIdol让我更近了一步,如果我将数据源从我原来的DataTable切换到ArrayList,那么一切正常……导致这种情况的原因是什么?

编辑2事实certificate我的DataTable有多个相同的值,因此索引被视为与具有相同值的所有项目相同…感谢那些帮助过的人!

foo()函数调用的输出是什么?

手动填充列表框,您可以将索引设置为您想要的任何内容(例如全部为0) – 因此在某些情况下设置给定的dataSource会发生同样的事情(一个指定我认为的索引)。 如果所有项索引都为0,结果是不会引发SelectedIndexChanged事件(索引不会改变!)并且一切都搞砸了:在回发后选择将返回到列表中的第一项。

这可以解释它 – 我无法想到其他任何东西 – 它在.NET 2.0上运行正常我使用带有字符串的ArrayList来填充listBox。

我可以重现您的问题的唯一方法是将所有索引设置为0。

我想在ListBox中添加一个监视并在运行时检查索引以确保它们不是全部为零。

这里真正的问题是事件的顺序。 当您在page_load中进行数据绑定时,会覆盖已发布的数据,这就是为什么未在列表框中设置选择的原因。 您可以通过将绑定逻辑移动到Page_Init来轻松克服此问题。

如果您的列表框项目相同,则所选索引将设置为0.要纠正它,将不同的值设置为item.value并让item.text保持不变..然后选择的索引将正确显示。

数据绑定DropDownLists / ListBox是痛苦的,因为它们经常绑定到错误的值。

我已经放弃使用DataBind(),只是使用Foreach循环:

 foreach (Item i in DataSet) { listBox.Items.Add(etc); } 

将数据加载到Page_Init而不是Page_Load。 在Page_init期间必须填充数据以便在PostBack中可用。

它看起来像你在每个页面加载上创建一个新的事件处理程序。 这可能会导致问题。 为什么不以声明方式附加事件处理程序:

  

另外,为什么不直接引用控件而不是铸造?

 protected void lbox_SelectedIndexChanged(object sender, EventArgs e) { int index = lbox.selectedIndex; } 

也适合我。 你的foo()每次都返回相同的值吗?

正如旁注:如果可能的话,你应该在OnInit中进行数据绑定(每次都是在GET上)。 如果你在调用base.OnInit(…)之前这样做,你的列表框的内容将不必序列化和反序列化到viewstate和通过线路发送到客户端(是的,你将会命中数据库更多,但你将会遇到位于本地子网上的系统,甚至是同一台机器上的系统。此外,数据库可能会缓存结果)。

如果要构建高性能网站,则需要仔细查看使用ViewState的方式。 我强烈推荐这篇文章: TRULY了解ViewState

您是否考虑过提前加载数据 – 例如在页面/用户控件上的OnInit事件中。 这是在加载回发数据之前发生的,因此可以在处理变更之前进行? 我相信这应该有用 – 但你可能想要关闭viewstate!

我不知道它是否有所作为,但我通常将我的控件附加到首页上的事件而不是代码隐藏中。 在你的例子中,我会做:

  

除此之外,我将validationViewState是否已启用。 可以在控件,页面甚至站点级别调整ViewState。