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 для получения вашей базы данных.