下拉列表中的第一项根本不触发SelectedIndexChanged事件

11

我有以下简单代码:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="testForm.aspx.cs" Inherits="Orbs.testForm" %>
<html>
<body>
    <form id="form1" runat="server">
        <asp:DropDownList ID="dropdown1" runat="server" AutoPostBack="true" OnSelectedIndexChanged="dropdown1_SelectedIndexChanged" ViewStateMode="Enabled">
            <asp:ListItem Value="1" Text="Item 1" />
            <asp:ListItem Value="2" Text="Item 2" />
            <asp:ListItem Value="3" Text="Item 3" />
            <asp:ListItem Value="4" Text="Item 4" />
            <asp:ListItem Value="5" Text="Item 5" />
        </asp:DropDownList>
        <asp:Label runat="server" ID="label1"></asp:Label>
    </form>
</body>
</html>

这是我的后台代码

using System;

namespace Orbs {
    public partial class testForm: System.Web.UI.Page {
        protected void Page_Load(object sender, EventArgs e) {
            label1.Text = "???!!";
        }

        protected void dropdown1_SelectedIndexChanged(object sender, EventArgs e) {
            label1.Text = "Fired on " + dropdown1.SelectedValue;
        }

    }
}

当我第一次进入页面时,label1 显示 '???!!'。现在我从下拉列表中选择一个项目,label1 显示正确的值,但是当我选择下拉列表中的第一个项目时,它再次显示 ???!! 而不是 Fired on 1

我做错了什么?

编辑:我注意到如果我在下拉列表中的任何项目上添加 Selected="True",那么该项目将成为受害者,并且不会触发事件!


哦,抱歉,你能看到事件上的断点吗? - hackp0int
不,当我选择第一个项目时它没有触发。选择其他项目会触发它。 - AaA
我认为当您选择第一项时,索引并没有改变,因为它实际上是加载时的相同索引。 - V4Vendetta
@V4Vendetta:在选择第一个值之前,我先选择了不同的值,然后页面也刷新了,这意味着问题不是出在客户端,而是出在服务器端某个地方出了问题。 - AaA
在我的端上似乎正常工作,你还做了其他事情吗?或者你可以尝试使用干净的构建。 - V4Vendetta
7个回答

18

对于仍然遇到此问题的任何人;我用一种不同但更简单的方法解决了它: 只需将一个虚拟的ListItem添加到DropDownList的开头,并将该项的Enabled属性设置为false。 例如:

<asp:DropDownList ID="dropdown1" runat="server" AutoPostBack="true" OnSelectedIndexChanged="dropdown1_SelectedIndexChanged" ViewStateMode="Enabled">
        <asp:ListItem Value="" Text="" Enabled="false" />
        <asp:ListItem Value="1" Text="Item 1" />
        <asp:ListItem Value="2" Text="Item 2" />
        <asp:ListItem Value="3" Text="Item 3" />
        <asp:ListItem Value="4" Text="Item 4" />
        <asp:ListItem Value="5" Text="Item 5" />
    </asp:DropDownList>

这是因为第一项通常不是实际选项,所以它的行为是这样的吗? - Animate_Ant

4

我自己解决了这个问题,

我在某个地方读到,关闭ViewStateMode会导致DropDownList无法正常工作。在我的 Web 应用程序中,我必须关闭 ViewStateMode 来完成一些全局任务,并逐个开启。

不知何故,在 DropDownList 上启用 ViewStateMode 不起作用,我甚至尝试为页面和母版页启用 ViewStateMode,但仍然无法使 DropDownList 正常工作。只有当我在 web.config 中启用 ViewStateMode 时,它才能正常工作。

由于在 web.config 中启用 ViewStateMode 不是一个选择,我找到了另一种解决方案。我在这里提供这个解决方案,希望能帮助到别人。

  • 向您的表单添加一个 HiddenField
  • Page_Load 中将 HiddenField 的值与 Request.Forms[DropDownList1.UniqueID] 进行比较。
  • 如果它们不同,则手动调用SelectedIndexChanged
  • HiddenField 的值设置为 Request.Forms[DropDownList1.UniqueID] 的值。

4
我来跟进一下。我在下拉控件上加了ViewStateMode=Enabled,问题就解决了。也许现在和以前有些不同了。 - Edyn
如果您检查我的示例代码,ViewStateMode=Enabled 已经存在,但我在 web.config 中禁用了它,但它并没有起作用。 - AaA
将ViewStateMode=Enabled属性应用于下拉控件对我也起作用了。 - Kayes
EnableViewState="true"对于控件在我这里没有生效,但是对于页面却有效。我使用的是ASP.NET 4.5.2。如上所述,ViewStateMode="Enabled"也没有生效。为什么会有两个听起来一样的选项呢? - Mike Grimm
从MSDN文档中翻译:页面或控件的ViewStateMode属性仅在EnableViewState启用时才起作用。有时为了减少页面内缓存数据的大小,关闭页面的视图状态是可取的。 - AaA

1

这个问题涵盖了所有可能性,比其他帖子更好,因此我添加了这个明确的答案。在我的情况下,@Edyn的评论起作用了,即使原始问题已经解决了:

在下拉控件本身上设置ViewStateMode="Enabled"
我还在页面声明的顶部设置了它,以防万一。

这是.NET 4.0,所以可能有些东西已经改变了(但肯定没有很好地解决)。


1

我也遇到了同样的问题 - 当选择第一个选项时,SelectedIndexChanged不会触发。

我的解决方案并不完美(不确定是否聪明,但对我有效),

在Page_Load中,我添加了以下脚本:

if (!IsPostBack)
        {

            //bind data first time
        }
        else
        {
            int ddlSortByValue = int.Parse(ddlSortBy.SelectedValue);
            if (ddlSortByValue == 0)
            {
                ddlSortBy_SelectedIndexChanged(this, EventArgs.Empty);
            }

        }

这样我就强制触发了SelectedIndexChanged事件


你的解决方案仅在下拉列表中的第一项为所选项时才有效(如果选择了列表中的其他项,则无效),并且你的值应该是数字(如果你的值是字符串,它将无效)。 - AaA

1

我曾经遇到过同样的问题,但是我通过手动调用onindexchanged函数来解决它,代码如下:

ddl_SelectedIndexChanged(null, null);

我知道这可能不是最完美的方法,但对我来说它起作用了。

如果您手动调用SelectedIndexChanged方法,且用户选择的不是第一个项目,则该方法将运行两次。 - AaA

0
在我的情况下,这是因为我使用了一个本地的dropdownlist变量来引用那个下拉列表,并在函数结束时处理掉了该变量。我在设置数据源后添加了第一项到dropdownlist中。花了我2个小时才找到这个问题,当我移除dispose调用后,它完美地工作了。

0

这是因为您在每个页面事件中将标签设置为“???!!”。

您需要修改页面加载以检测是否发生了回发。

    protected void Page_Load(object sender, EventArgs e) {
        if(!IsPostBack)
        {
            label1.Text = "???!!";
        }
    }

我已经从另一个人那里得到了完全相同的答案,但他删除了评论。如果我从“Page_Load”中删除该行,仍然无法触发“dropdown1_SelectedIndexChanged”事件,标签仍为空。 - AaA

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接