ASP.NET Web Forms DropDownList имеет SelectedValue, который является недопустимым, поскольку он не существует в списке элементов
Прежде всего возникли вопросы (DropDownList имеет SelectedValue, который является недопустимым, потому что он не существует в списке элементов, DropDownList " имеет значение SelectedValue, которое недействительно, потому что оно не существует в списке элементов, asp: Ошибка DropDownList: "DropDownList1" имеет SelectedValue, который недействителен, потому что он не существует в списке элементов) об этом и предлагается обходные пути, но мой вопрос действительно ПОЧЕМУ это происходит. Более того, я не удовлетворен предлагаемыми обходными решениями, и я нахожу их довольно уродливыми.
Итак, есть страница с выпадающим списком и кнопкой:
<%@ 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, но все же получил то же исключение. Является ли эта ошибка в контроле или что-то мне не хватает. Являются ли уродливые обходные пути из других вопросов единственным решением?
Примечание. Ошибка будет воспроизведена, даже если кнопка будет удалена, и весь код будет перемещен в одном обработчике событий. Просто привяжите один раз заданное выбранное значение и снова привяжите его.
Ответы
Ответ 1
Я отправил сообщение об ошибке 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
Почему я получаю исключение.
После вызова функции Page_Init() ddlTest привязан к 3 элементам: "1", "2" и "3" . Затем вы устанавливаете SelectedValue на "3" и управляете всеми вещами, связанными с элементом управления DropDownList. Но элемент управления по-прежнему привязан к предыдущему списку - вы еще не вызвали .DataBind(), даже если вы изменили свойства DropDownList. Исключение возникает из-за того, что элемент управления все еще привязан к {1, 2, 3}, он висит на предыдущем .SelectedValue, и вы только что попытались .DataBind() его в список, который не включает "3" .
Ответ 3
У меня была аналогичная проблема, и я исправил ее, добавив метод 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>
Ответ 4
1) Как написано, ваш пример действительно выдает исключение на ddlTest.SelectedValue = "";
, так как в коллекции нет элемента с Value
of "". Я думаю, что это ожидалось при любых обстоятельствах.
2) Я получаю исключение каждый раз, когда я пытаюсь установить SelectedValue
или SelectedIndex
для DDL на то, что будет недействительным к моменту визуализации 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...
}
Итак, какой вывод можно сделать из этого? Похоже, проблема связана с установкой свойства SelectedIndex
или SelectedValue
для DDL до того, как содержимое DDL может быть изменено в одном и том же цикле страниц. Если ранее установленное значение все еще доступно в новом содержимом DropDownList.Items
, вы находитесь в бизнесе. Но если это не так, вы получите исключение.
Я предполагаю, что это имеет какое-то отношение к потокобезопасности, но я не эксперт в этом, поэтому, надеюсь, кто-то может прокомментировать.
Ответ 5
В моем случае я имел DropdownList
в templatedfield
of gridview
. Теперь datasource
сетки имеет элемент employeeid
. У меня есть это в сохраненной процедуре, isnull(employeeid,0)
для источника данных и угадайте, что DropdownList
не имеет значения 0 на своих элементах; поэтому я изменил это на isnull (employeeid, 1), потому что первый элемент в DropdownList
имеет employeeid =1
и эта проблема решена
Ответ 6
Поскольку нет никакой базы данных, когда ваша страница перезагружается (выполняется postback), вы должны добавить элемент управления SqlDataSource в ваш .aspx файл, даже на странице перезагрузки распознайте DropDownList DataSource. Затем вы можете использовать InsertCommand, UpdateCommand, DeleteCommand и SelecCommand для получения вашей базы данных.