Ошибка:Выбранное значение, которое является недопустимым, поскольку оно не существует в списке элементов

StackOverflow https://stackoverflow.com/questions/1317262

Вопрос

У меня есть Gridview, который привязывается к ObjectDataSource (objStudentDetails).В режиме редактирования / вставки Gridview одним из полей является выпадающий список, который получает параметры списка выбора из таблицы подстановки.У меня есть этот выпадающий список, привязанный к другому элементу управления ObjectDataSource (objStateList), который представляет таблицу поиска.Это работает нормально до тех пор, пока значение в objStudentDetails ObjectDataSource совпадает с одним из значений в objStateList ObjectDataSource, по крайней мере, в случае непустого строкового значения в любом случае.

objStateList имеет эти значения (из сохраненной процедуры, которая его загружает - идентификатор # 6 является пустой строкой "):

StateId     State
----------- -----
6             
4           AL
1           GA
3           KY
2           TN

objStudentDetails имеет эти значения (из сохраненной процедуры, которая его загружает):

FirstName   LastName   State
----------- ---------- -----
tone        smith      TN

Или он мог бы иметь этот результирующий набор (состояние - это пустая строка - "):

FirstName   LastName   State
----------- ---------- -----
jenny       johnson     

В первом результирующем наборе objStudentDetails выпадающий список состояния в EditItemTemplate отображается нормально.Однако во втором наборе результатов я получаю эту ошибку:

'ddlEditState' has a SelectedValue which is invalid because it does not exist in the list of items.
Parameter name: value 

Я бы подумал, что, поскольку моя таблица поиска имеет значение с пустой строкой, значение objStudentDetails с пустой строкой для state будет соответствовать, но что-то работает не так, как я ожидаю.

Вот мой код EditItemTemplate из Gridview:

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

Есть какие-нибудь идеи?

Это было полезно?

Решение

Начните с установки для свойства AppendDataBoundItems обоих выпадающих списков значения true.Затем добавьте НУЛЕВОЙ ListItem, добавив следующее <asp: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>

Другие советы

Я подозреваю, что существует много различных сценариев, которые могут вызвать эту ошибку.В моем случае у меня был выпадающий список, помещенный в поле шаблона.Выпадающий список был привязан к своему собственному objectdatasource, а его свойство selectedvalue было привязано к полю из собственного (отдельного) источника данных gridview.

Теперь, в моем конкретном сценарии, проблема заключалась в состоянии гонки.Источник данных gridview был заполнен и привязан до того, как наступила очередь выпадающих списков.Это также означало, что выбранные значения выпадающих списков устанавливались ДО того, как элементы выпадающих списков были созданы с помощью их собственных привязок.

Я уверен, что должно быть лучшее решение, но у меня не было много времени на исследования.Я отключил gridview и выпадающие списки от их источников данных (что означает удаление назначений из конструктора) и выбрал привязку программно.Таким образом, я могу явно привязать выпадающие списки, чтобы значения их элементов были доступны, когда привязан сам gridview.

Пока все так хорошо.Всего несколько дополнительных строк кода в Page_Load

AppendDataBoundItems="True"> работает, но не во всех случаях.Создание выпадающего списка внутри GridView по-прежнему остается загадкой, которую Microsoft должна разрешить.Они говорят, что разработка на ASP происходит намного быстрее, чем на PHP.Что ж, это мой третий день в этом маленький проблема и до сих пор не имеет решения.

Хорошо, поскольку это распространенная проблема, я думаю, стоит на самом деле опубликовать ответ:После долгих поисков я нашел два решения - ну, одно исправленное и одно реальное.

  1. Латание:Установите параметр DDL AppendDataBoundItem=true и добавить вручную один элемент в список (т.е."Пожалуйста, выберите" с нулевым значением):

    < asp: идентификатор выпадающего списка="DropDownList5 runat="сервер" AppendDataBoundItems="True" ...> < asp: Список> Пожалуйста, выберите< /asp:Список> < /asp: выпадающий список>

Кажется, это работает примерно в 80% случаев.У меня была странная ситуация, когда мне пришлось обновить существующий (и рабочий) запрос, используемый DDL, чтобы разрешить другое значение параметра - Запрос был чем-то похож на SELECT ID, Name from EMPLOYEES where Department =@Department и первоначально @Department могло быть равно только "Планировщикам" и "Мастерской" - после добавления "Логистики" DDL таинственным образом перестал работать ТОЛЬКО для нового значения department.

  1. Правильное решение:Привязать DDL во время GridView_RowDataBound событие (источник благодаря Эта статья

Мой параметр берется в виде текста из ярлыка (настроенного где-то в другом месте).

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

И метод 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;
            }
        }
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top