【问题标题】:ASP.NET Web Forms DropDownList has a SelectedValue which is invalid because it does not exist in the list of itemsASP.NET Web 窗体 DropDownList 有一个无效的 SelectedValue,因为它不存在于项目列表中
【发布时间】:2011-08-18 16:12:01
【问题描述】:

首先有关于这个的问题(DropDownList has a SelectedValue which is invalid because it does not exist in the list of itemsDropDownList "has a SelectedValue which is invalid because it does not exist in the list of items"asp:DropDownList Error: 'DropDownList1' has a SelectedValue which is invalid because it does not exist in the list of items)并且有建议的解决方法,但我的问题是为什么会发生这种情况。更重要的是,我对建议的解决方法不满意,我觉得它们很丑。

所以有一个带有下拉列表和按钮的页面:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm2.aspx.cs" Inherits="TestWebApplication.WebForm2" ViewStateMode="Disabled" %>

<html lang="en" >
<body>
    <form id="form1" runat="server">
    <div>
        <asp:DropDownList ID="ddlTest" runat="server">
        </asp:DropDownList>
        <asp:Button Text="Test" ID="btnTest" runat="server" onclick="btnTest_Click" />
    </div>
    </form>
</body>
</html>

我将 ddlTest 与 Page_Init 上的一些项目绑定,然后在 btnTest_Click 中再次绑定:

using System;

namespace TestWebApplication
{
    public partial class WebForm2 : System.Web.UI.Page
    {
        protected void Page_Init(object sender, EventArgs e)
        {
            //SelectedIndex is -1, SelectedValue is "", SelectedItem is null
            ddlTest.DataSource = new[] { 1, 2, 3 };
            ddlTest.DataBind();
            ddlTest.SelectedValue = "3";
        }

        protected void btnTest_Click(object sender, EventArgs e)
        {
            //SelectedIndex is 2, SelectedValue is "3", SelectedItem is {3}
            ddlTest.ClearSelection();
            //SelectedIndex is 0, SelectedValue is "1", SelectedItem is {1}
            ddlTest.SelectedIndex = -1; //Nothing changes including SelectedIndex
            ddlTest.SelectedValue = ""; //Nothing changes including SelectedValue
            ddlTest.Items.Clear();
            //SelectedIndex is -1, SelectedValue is "", SelectedItem is null
            ddlTest.DataSource = null; //Nothing changes except for the DataSource property
            ddlTest.DataSource = new[] { 1, 2 };
            ddlTest.DataBind();//Exception!
            //'ddlTest' has a SelectedValue which is invalid because it does not exist in the list of items.
            //Parameter name: value
        }
    }
}

为什么会出现异常。我尝试了这些的不同版本,但它们都不起作用。我尝试仅使用 ClearSelection,但仍然遇到相同的异常。这是控件中的错误还是我想念的东西。其他问题的丑陋解决方法是唯一的解决方案吗?

注意 - 即使按钮被移除并且所有代码都在单个事件处理程序中移动,该错误也是可重现的。只需绑定一次设置选定的值并再次绑定。

【问题讨论】:

  • 我不确定您所看到的确切内容,但我不明白您为什么采用这种方法。首先,我将创建一个单独的方法来初始化控件。然后我会从Page_Load 调用这个方法,如果!IsPostBack。然后我会再次从您的按钮单击处理程序中调用相同的方法 进行任何更改之后。你有什么理由使用Page_Init 事件吗?
  • @J. Wood +1 推荐 Page_Load,而不是 Page_Init。页面生命周期可能非常令人沮丧,如果可能的话,最好避免在其深处徘徊。
  • 可能是他试图避免弄脏 ddl 的视图状态......他显然没有在这里尝试完成任何事情,这只是一个演示错误情况的练习。
  • 我使用 Page_Init 以避免覆盖 DropDownList 中的回发信息(我已禁用 ViewState,如 page 指令中所述)。现实世界的示例是一个按钮 Delete,它从列表中删除选定的值并重新绑定它。在这种情况下,我当然可以删除它或将值设置为其他值,但可能存在更复杂的情况,即删除更难(如果我必须删除几个相关项目怎么办)。 @Jonathan Wood 在现实世界的代码中,我确实有一个在两个地方都可以调用的方法。

标签: asp.net webforms


【解决方案1】:

1) 如所写,您的示例实际上在ddlTest.SelectedValue = ""; 上引发了异常,因为集合中没有Value 为“”的项目。我认为这在任何情况下都是可以预料的。

2) 每次我尝试将 DDL 的 SelectedValueSelectedIndex 设置为在呈现 DDL 时将无效的内容时都会遇到异常。但是直到DropDownList.Items 集合实际更改后才会发生异常,例如DropDownList.Databind()。我做的第一件事就是对 Page_Init 进行了更改:

protected void Page_Init(object sender, EventArgs e)
{
    //SelectedIndex is -1, SelectedValue is "", SelectedItem is null
    if (!IsPostBack)
    {
        ddlTest.DataSource = new[] { 1, 2, 3 };
        ddlTest.DataBind();
        ddlTest.SelectedValue = "3";
    }
}

现在有趣的是第一个示例抛出异常,但第二个没有。他们都设置了一个当时有效的SelectedValue,但第一个示例中的值(“3”)在页面呈现时将无效:

protected void btnTest_Click(object sender, EventArgs e)
{
    //SelectedIndex is 2, SelectedValue is "3", SelectedItem is {3}
    ddlTest.SelectedValue = "3"; 
    //SelectedIndex is 2, SelectedValue is "3", SelectedItem is {3}
    ddlTest.ClearSelection();
    //SelectedIndex is 0, SelectedValue is "1", SelectedItem is {1}
    ddlTest.Items.Clear();
    //SelectedIndex is -1, SelectedValue is "", SelectedItem is null
    ddlTest.DataSource = null;
    ddlTest.DataSource = new[] { 1, 2 };
    ddlTest.DataBind(); //Exception!
    //'ddlTest' has a SelectedValue which is invalid because it does not exist in the list of items.
    //Parameter name: value
}

protected void btnTest_Click(object sender, EventArgs e)
{
    //SelectedIndex is 2, SelectedValue is "3", SelectedItem is {3} (from viewstate)
    ddlTest.SelectedValue = "2"; 
    //SelectedIndex is 1, SelectedValue is "2", SelectedItem is {3}
    ddlTest.ClearSelection();
    //SelectedIndex is 0, SelectedValue is "1", SelectedItem is {1}
    ddlTest.Items.Clear();
    //SelectedIndex is -1, SelectedValue is "", SelectedItem is null
    ddlTest.DataSource = null;
    ddlTest.DataSource = new[] { 1, 2 };
    ddlTest.DataBind(); //No Exception...
}

那么,我们可以从中得出什么结论呢?好吧,问题似乎是由于在同一页面周期中更改 DDL 的内容之前设置了 DDL 的 SelectedIndexSelectedValue 属性。如果之前设置的值在DropDownList.Items 的新内容中仍然可用,则说明您在营业。但如果它不在那里,你会得到一个例外。

我的猜测是这与线程安全有关,但我不是这方面的专家,所以希望有人可以发表评论。

【讨论】:

  • 奇怪的是它会为你在另一行抛出异常。您在哪个版本的 ASP.NET 上进行测试?
【解决方案2】:

为什么会出现异常。

调用 Page_Init() 后,ddlTest 已绑定到 3 个项目:“1”、“2”和“3”。然后将 SelectedValue 设置为“3”并操作与 DropDownList 控件相关的各种事物。 但该控件仍绑定到上一个列表 -- 即使您更改了 DropDownList 属性,您也没有再次调用 .DataBind()。发生异常是因为控件仍绑定到 {1, 2, 3},它挂在前一个 .SelectedValue 上,而您刚刚尝试将 .DataBind() 绑定到不包含“3”的列表。

【讨论】:

  • 如果我无法更改 SelectedValue 属性,如何绑定到不包含 3 的列表?好像是第 22 条军规。
  • 您确实可以更改它,但您需要在第一次调用 .DataBind() 之前完成所有更改。我在几个地方(错误地)更改 .SelectedValue 时遇到了同样的问题。在 .DataBind() 之后只打一个电话,你应该是金子。 +1 约瑟夫·海勒。
【解决方案3】:

我已针对该问题在 Connect 上提交了一个错误。它被解决为“不会修复”,在我看来这意味着它实际上是一个错误。提供了一种解决方法:

ddlTest.Items.Clear();
ddlTest.SelectedValue = null;

https://connect.microsoft.com/VisualStudio/feedback/details/666808/asp-net-dropdownlist-selectedvalue-is-persisted-which-results-in-exception-if-the-control-is-databound-second-time

我认为这是答案。

【讨论】:

  • 谢谢您,先生。更多证据表明我没有疯。
  • 太棒了。 2小时的谷歌搜索和调试......然后我找到了这个。我已经尝试将 selectedindex 设置为 -1,将 .AppendDataBoundItems 设置为 true,并在放入项目之前进行绑定。这些方法都不起作用。做到了!
  • 我确认这是唯一有效的答案。我试过 SelectedIndex=-1 并没有用。我想知道为什么真的是因为 SelectedValue = null SelectedIndex=-1, ClearSelection() 和 Item.Selected = false 应该都是同义词。我的应用程序正在从 NET11 迁移到 NET4。在 NET11 中,没有发生此错误。
【解决方案4】:

我遇到了类似的问题,并通过添加 DataBinding 方法解决了它。

protected void myDDL_DataBinding(object sender, EventArgs e)
{
    if (myDDL.SelectedIndex != -1)
    {
        myDDL.SelectedIndex = 0;
    }
}

在设计页面上...

<asp:DropDownList ID="myDDL" runat="server" 
    AutoPostBack="true" OnDataBinding="myDDL_DataBinding"
    OnSelectedIndexChanged="myDDL_SelectedIndexChanged">
</asp:DropDownList>

【讨论】:

    【解决方案5】:

    因为当你的页面被重新加载(回发发生)时没有任何数据源,你应该在你的.aspx文件中添加SqlDataSource控件,即使在重新加载页面时识别DropDownList的DataSource。然后您可以使用 InsertCommand、UpdateCommand、DeleteCommand 和 SelectCommand 来获取您的数据库。

    【讨论】:

      【解决方案6】:

      在我的情况下,我在templatedfieldgridview 中有DropdownList。现在 datasource 的网格有 employeeid 项目。我在存储过程中有这个,isnull(employeeid,0) 用于数据源,猜猜DropdownList在其项目上没有值 0;所以我把它改成了 isnull(employeeid,1) 因为DropdownList中的第一项有employeeid =1,这解决了问题

      【讨论】:

        猜你喜欢
        • 2011-08-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-15
        • 2014-01-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多