Asp.net 错误:SelectedValue无效,因为它不在项目列表中

Asp.net 错误:SelectedValue无效,因为它不在项目列表中,asp.net,gridview,drop-down-menu,edititemtemplate,Asp.net,Gridview,Drop Down Menu,Edititemtemplate,我有一个绑定到ObjectDataSource(objStudentDetails)的Gridview。在Gridview的编辑/插入模式下,其中一个字段是DropDownList,它从查找表中获取其拾取列表选项。我将此DropDownList绑定到另一个ObjectDataSource控件(objStateList),该控件表示查找表。只要objStudentDetails ObjectDataSource中的值与objStateList ObjectDataSource中的一个值匹配,它就可

我有一个绑定到ObjectDataSource(objStudentDetails)的Gridview。在Gridview的编辑/插入模式下,其中一个字段是DropDownList,它从查找表中获取其拾取列表选项。我将此DropDownList绑定到另一个ObjectDataSource控件(objStateList),该控件表示查找表。只要objStudentDetails ObjectDataSource中的值与objStateList ObjectDataSource中的一个值匹配,它就可以正常工作,至少在非空字符串值的情况下是如此

objStateList具有以下值(来自加载它的存储过程-ID#6是空字符串“”):

objStudentDetails具有以下值(来自加载它的存储过程):

或者它可以有此结果集(状态为空字符串-“”):

在第一个objStudentDetails结果集中,EditItemTemplate中的状态DropDownList显示良好。但是,在第二个结果集中,我得到了以下错误:

'ddlEditState' has a SelectedValue which is invalid because it does not exist in the list of items.
Parameter name: value 
我会认为,由于我的查找表有一个空字符串的值,因此状态为空字符串的objStudentDetails值会匹配,但有些东西并没有按照我期望的方式工作

以下是Gridview中的EditItemTemplate代码:

<EditItemTemplate>
  <asp:Panel ID="panEditState" runat="server">
    <asp:DropDownList ID="ddlEditState" runat="server" CssClass="GridviewDropdownlist"
      DataSourceID="objStateList" DataTextField="State" DataValueField="State"      
      SelectedValue='<%# Bind("State") %>'
      Width="50px">
</asp:DropDownList>
</asp:Panel>
</EditItemTemplate>

以及objStateList,它调用传递要查询的查找表的参数的方法:

<asp:ObjectDataSource ID="objStateList" runat="server" SelectMethod="GetDropdownData"     TypeName="AIMLibrary.BLL.DropdownData">
<SelectParameters>
<asp:Parameter Name="itemsToGet" DefaultValue="state" />
</SelectParameters>
</asp:ObjectDataSource>


有什么想法吗?

首先将两个DropDownList的AppendDataBoundItems属性都设置为true。接下来,通过向每个DropDownList添加以下
元素来添加空ListItem,以便声明性标记如下所示:

<asp:DropDownList ID="Categories" runat="server"
    DataSourceID="CategoriesDataSource" DataTextField="CategoryName"
    DataValueField="CategoryID" SelectedValue='<%# Bind("CategoryID") %>'
    AppendDataBoundItems="True">
    <asp:ListItem Value="">[nothing selected]</asp:ListItem>
</asp:DropDownList>

[未选择任何内容]

AppendDataBoundItems=“True”>有效,但并非在所有情况下都有效。在GridView中制作dropdownlist仍然是微软必须解决的一个谜。他们说ASP的开发比PHP快得多。这是我处理这个小问题的第三天,仍然没有解决方案。

我怀疑有许多不同的情况会导致这个错误。在我的例子中,我在模板字段中放置了一个下拉列表。下拉列表绑定到其自己的objectdatasource,其selectedvalue属性绑定到gridview自己的(单独的)数据源中的字段

现在,在我的特定场景中,问题在于比赛条件。gridview的数据源在下拉菜单出现之前就已经被填充和绑定了。这也意味着下拉列表的SelectedValue是在下拉列表项通过其自身绑定创建之前设置的

我肯定会有更好的解决办法,但我没有太多时间进行研究。我断开了gridview和下拉列表与它们的数据源的连接(这意味着从设计器中删除赋值),并以编程方式选择了绑定。这样,我可以显式地绑定下拉列表,以便在绑定gridview本身时,它们的项值可用


到目前为止,一切顺利。只需在页面中添加几行额外的代码就可以了,因为这是一个常见问题,所以我想应该发布一个答案:在仔细研究之后,我找到了两个解决方案——一个补丁和一个真正的补丁

  • 修补: 设置DDL设置
    AppendDataBoundItem=true
    并手动将一个元素添加到列表中(即带有空值的“请选择”):

    请选择

  • 这似乎在大约80%的情况下有效。当我不得不升级DDL使用的现有(和工作)查询以允许另一个参数值时,我遇到了一个奇怪的情况-查询类似于
    选择ID,来自员工的名称,其中Department=@Department
    和最初的
    @Department
    只能等于“计划员”和“车间”-在添加“物流”后,DDL神秘地停止工作,只为部门的新价值

  • 正确的解决方案:在
    GridView\u RowDataBound
    事件期间绑定DDL(感谢
  • 我的参数作为标签中的文本(在其他地方设置)

    以及GetData方法:

       private DataTable GetData (SqlCommand cmd)
    {
        string strConnString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
        using (SqlConnection con = new SqlConnection(strConnString))
        {
            using (SqlDataAdapter sda = new SqlDataAdapter())
            {
                cmd.Connection = con;
                sda.SelectCommand = cmd;
                using (DataTable dt= new DataTable())
                {
                    sda.Fill(dt);
                    return dt;
                }
            }
        }
    }
    

    非常好用-谢谢!我用它来表示空列表项:我使用模型绑定,所以这个答案最合适。
    <asp:ObjectDataSource ID="objStateList" runat="server" SelectMethod="GetDropdownData"     TypeName="AIMLibrary.BLL.DropdownData">
    <SelectParameters>
    <asp:Parameter Name="itemsToGet" DefaultValue="state" />
    </SelectParameters>
    </asp:ObjectDataSource>
    
    <asp:DropDownList ID="Categories" runat="server"
        DataSourceID="CategoriesDataSource" DataTextField="CategoryName"
        DataValueField="CategoryID" SelectedValue='<%# Bind("CategoryID") %>'
        AppendDataBoundItems="True">
        <asp:ListItem Value="">[nothing selected]</asp:ListItem>
    </asp:DropDownList>
    
        protected void GridView5_RowDataBound(object sender, GridViewRowEventArgs e)
        {
    
        //********** this  is a workaround for the annoying problem with dropdownlist in gidview without adding new item ************
        if (e.Row.RowType == DataControlRowType.DataRow && GridView5.EditIndex == e.Row.RowIndex)
        {
            DropDownList DropDownList5 = (DropDownList)e.Row.FindControl("DropDownList5");
            string query = "SELECT gkey as empID, name FROM [employees] where department=@department";
            SqlCommand command = new SqlCommand(query);
            command.Parameters.AddWithValue("@department", lblDepartment.Text);
            DropDownList5.DataSource = GetData(command);
            DropDownList5.DataTextField = "name";
            DropDownList5.DataValueField = "empID";
            DropDownList5.DataBind();
        }
    
       private DataTable GetData (SqlCommand cmd)
    {
        string strConnString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
        using (SqlConnection con = new SqlConnection(strConnString))
        {
            using (SqlDataAdapter sda = new SqlDataAdapter())
            {
                cmd.Connection = con;
                sda.SelectCommand = cmd;
                using (DataTable dt= new DataTable())
                {
                    sda.Fill(dt);
                    return dt;
                }
            }
        }
    }