【问题标题】:selectedIndex is lost during postbacks - ASP.NETselectedIndex 在回发期间丢失 - ASP.NET
【发布时间】:2008-12-03 19:49:06
【问题描述】:

我有一个列表框控件:

<asp:ListBox runat="server" id="lbox" autoPostBack="true" />

后面的代码类似:

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; }

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

看起来这可能是一个视图状态问题?如何修复它以使选择索引在回发中保持不变?

没有 ajax,这是 .NET 1.0。

谢谢。

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

编辑 2 原来我的 DataTable 有多个相同的值,因此索引被视为与具有相同值的所有项目相同...感谢帮助的人!

【问题讨论】:

  • .NET 2.0 上完全相同的东西对我来说很好
  • 很高兴看到您的问题得到解决

标签: c# .net asp.net viewstate


【解决方案1】:

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

【讨论】:

  • 很好的建议!我一直认为这与禁用视图状态有关,但即使禁用视图状态,当我将绑定代码移动到 Init 时,我的下拉列表也能正常工作
【解决方案2】:

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

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

这可以解释它 - 我想不出其他任何东西 - 它在 .NET 2.0 上对我来说工作正常 我正在使用带有字符串的 ArrayList 来填充列表框。

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

我会说向 ListBox 添加一个监视并在运行时检查索引以确保它们不全为零。

【讨论】:

  • 我正在与数据表进行数据绑定......这真的让我大吃一惊......我当然认为这是一件容易解决的事情......
  • 尝试使用一个数组列表,看看会发生什么,只是出于好奇。确保 DataTable 只有一列
  • 我刚刚尝试了一个数组列表,它可以工作......现在我只需要弄清楚我的数据表有什么问题......虽然它来自数据库查询......有什么想法吗?
  • 我认为它有不止一列,第二列被解释为索引(尚未尝试)。您是否尝试将手表添加到列表框中并查看索引?如果它们都一样,那就是它
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

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

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

    【讨论】:

      【解决方案5】:

      在 Page_Init 而不是 Page_Load 中加载数据。数据必须在 Page_init 期间填充才能在 PostBack 中可用。

      【讨论】:

        【解决方案6】:

        在我看来,您在每次页面加载时都创建了一个新的事件处理程序。这可能会导致问题。为什么不以声明方式附加事件处理程序:

        <asp:ListBox runat="server" id="lbox" autoPostBack="true" OnSelectedIndexChanged="lbox_SelectedIndexChanged" />
        

        另外,为什么不直接引用控件,而不是强制转换?

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

        【讨论】:

        • 我正在强制转换,因为使用 .net 1.0,您必须在后面的代码中将控件作为实例变量,在 .NET 2.0 + 中,控件可以在没有实例变量的情况下访问。
        • 确实,我每次都拿出代码来创建事件处理程序,现在一切正常。现在,我真正想知道的是,这些一直投反对票的人是谁?我有点厌倦了——这不是我第一次使用被否决的解决方案,只是发现它是最好的答案。
        【解决方案7】:

        也适合我。您的 foo() 是否每次都返回相同的值?

        顺便说一句:如果可能,您应该真正在 OnInit 中进行数据绑定(每次,而不仅仅是在 GET 上)。如果您在调用 base.OnInit(...) 之前执行此操作,则列表框的内容不必在视图状态和视图状态之间进行序列化和反序列化并通过线路发送到客户端(是的,您将点击数据库更多,但您将访问位于本地子网甚至同一台计算机上的系统。此外,数据库可能会缓存结果)。

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

        【讨论】:

        • 我的代码实际上并没有像我的示例所示那样执行数据绑定,我实际上是在单击按钮时进行数据绑定...
        【解决方案8】:

        您是否考虑过更早地加载数据 - 例如在页面/用户控件上的 OnInit 事件中。这发生在加载回发数据之前,因此在可以处理 on-change 之前?我相信这应该可行 - 但您可能想要关闭视图状态!

        【讨论】:

          【解决方案9】:

          我不知道这是否会有所不同,但我通常将控件附加到首页上的事件而不是代码隐藏中。在您的示例中,我会这样做:

          <asp:ListBox runat="server" id="lbox" autoPostBack="true" OnSelectedIndexChanged="lboxScorecard_SelectedIndexChanged"  />
          

          除此之外,我会验证 ViewState 是否已启用。 ViewState 可以在控件、页面甚至站点级别关闭。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-05-29
            • 2014-11-04
            • 2016-07-15
            • 1970-01-01
            • 1970-01-01
            • 2012-06-18
            • 1970-01-01
            相关资源
            最近更新 更多