web-dev-qa-db-ja.com

ASP.NET Webフォームの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のみを使用してみましたが、同じ例外が発生しました。このバグはコントロールにありますか、それとも私が見逃しているものですか。他の質問からの醜い回避策が唯一の解決策ですか?

注-ボタンが削除され、すべてのコードが単一のイベントハンドラーで移動された場合でも、バグは再現可能です。一度設定した値をバインドして再度バインドするだけです。

16
Stilgar

この問題について、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

私はこれが答えだと思います。

32
Stilgar

なぜ例外が発生するのですか?

Page_Init()が呼び出された後、ddlTestは「1」、「2」、「3」の3つの項目にバインドされています。次に、SelectedValueを「3」に設定し、DropDownListコントロールに関連するあらゆる種類のものを操作します。 ただし、コントロールは引き続き前のリストにバインドされています-DropDownListプロパティを変更しても、.DataBind()を再度呼び出すことはありません。例外は、コントロールがまだ{1、2、3}にバインドされており、前の.SelectedValueにぶら下がっていて、「3」を含まないリストに.DataBind()しようとしたために発生します。

3
Mark A

同様の問題が発生し、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>
3
WEFX

1)記述されているように、コレクションにはValueが ""のアイテムがないため、例では実際には_ddlTest.SelectedValue = "";_に例外がスローされます。これはどんな状況でも予想されることだと思います。

2)DDLのSelectedValueまたはSelectedIndexを、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";
    }
}
_

ここで興味深いのは、この最初の例では例外がスローされますが、2番目の例では例外がスローされないことです。どちらもその時点で有効な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...
}
_

では、これからどのような結論を導き出すことができますか?問題は、同じページサイクルでDDLの内容が変更される前に、DDLのSelectedIndexまたはSelectedValueプロパティを設定したことが原因のようです。以前に設定した値が_DropDownList.Items_の新しいコンテンツでまだ使用できる場合は、ビジネスを行っています。ただし、そこにない場合は例外が発生します。

私の推測では、これはスレッドの安全性と関係がありますが、私はその専門家ではないので、誰かがコメントできることを願っています。

2
pseudocoder

私の場合、DropdownListtemplatedfieldgridviewがありました。これで、グリッドのdatasourceemployeeidアイテムが含まれました。これは保存されたプロシージャにあり、データソースのisnull(employeeid,0)であり、DropdownListの項目に値0がないものを推測します。 DropdownListの最初の項目にemployeeid =1があり、これで問題が解決したため、これをisnull(employeeid、1)に変更しました。

0
hassan