Ошибка:Выбранное значение, которое является недопустимым, поскольку оно не существует в списке элементов
-
19-09-2019 - |
Вопрос
У меня есть 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.Что ж, это мой третий день в этом маленький проблема и до сих пор не имеет решения.
Хорошо, поскольку это распространенная проблема, я думаю, стоит на самом деле опубликовать ответ:После долгих поисков я нашел два решения - ну, одно исправленное и одно реальное.
Латание:Установите параметр DDL
AppendDataBoundItem=true
и добавить вручную один элемент в список (т.е."Пожалуйста, выберите" с нулевым значением):< asp: идентификатор выпадающего списка="DropDownList5 runat="сервер" AppendDataBoundItems="True" ...> < asp: Список> Пожалуйста, выберите< /asp:Список> < /asp: выпадающий список>
Кажется, это работает примерно в 80% случаев.У меня была странная ситуация, когда мне пришлось обновить существующий (и рабочий) запрос, используемый DDL, чтобы разрешить другое значение параметра - Запрос был чем-то похож на SELECT ID, Name from EMPLOYEES where Department =@Department
и первоначально @Department
могло быть равно только "Планировщикам" и "Мастерской" - после добавления "Логистики" DDL таинственным образом перестал работать ТОЛЬКО для нового значения department.
- Правильное решение:Привязать 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;
}
}
}
}