2

私の ASP.NET サイトには、サーバーによっていくつかの要素が入力された 2 つの選択リストがあります。

// .aspx
<asp:dropdownlist id="abc" runat="server"></asp:dropdownlist>
<asp:dropdownlist id="def" runat="server"></asp:dropdownlist>

// .aspx.cs
abc.Items.Add(new ListItem("element1", "value1"));
def.Items.Add(new ListItem("element1", "value1"));

理由が複雑すぎて説明できないため、JavaScript を使用して選択リストのオプションを変更し、いくつかの値を追加する必要があります。

// In the <head> of the .aspx page
var abcList = document.getElementById("abc");
var defList = document.getElementById("def");
var newAbcElement = new Option("element2", "value2", false, false);
var newDefElement = new Option("element2", "value2", false, false);
abcList.options[abcList.length] = newAbcElement;
defList.options[defList.length] = newDefElement;

もちろん、フォームをサーバーに送り返すとすぐに、これは検証を台無しにします (送信するか、他のフォーム要素からの PostBack としてAutoPostBack="true")。

ポストバックまたはコールバック引数が無効です。イベントの検証は、設定で使用するか、ページで <%@ Page EnableEventValidation="true" %> を使用して有効にします。セキュリティ上の理由から、この機能は、ポストバック イベントまたはコールバック イベントへの引数が、それらを最初にレンダリングしたサーバー コントロールから発信されていることを確認します。データが有効で期待される場合は、ClientScriptManager.RegisterForEventValidation メソッドを使用して、検証のためにポストバックまたはコールバック データを登録します。

現在、ページのデザイン全体を完全にオーバーホールするためのリソースと予算がありません。すべてを書き直す必要がない、ドロップダウンリストを変更する最も速く簡単な方法は何ですか?

フォームを送信するときに、JavaScript を介して追加された値が CodeBehind ファイルによって認識されるようにするには?

4

3 に答える 3

1

いくつかのオプションがあります。

まず、サーバー側がの可能なすべてのアイテムを生成するようにコードを書き直してからDropDownList、JavaScriptで、新しいアイテムを追加する代わりに、不要なアイテムを削除します。

2番目のオプションは、から派生したカスタムクラスを作成することSystem.Web.UI.WebControls.DropDownListです。クラスには、以下に示す1つのメソッドが含まれている必要があります。重要な点は、カスタムクラスにSystem.Web.UI.SupportsEventValidationAttribute追加されないことです。したがって、DropDownList基本メソッドはイベント検証を自動的にスキップします。次に、使用法をからメソッドに置き換え<asp:dropdownlist>ます。

.aspxコードを変更できない場合(または置き換えるドロップダウンリストが大量にある場合)は、構成でタグマッピングを使用できます。

namespace Project.MyWebControls
{
    public class MyDropDownList : System.Web.UI.WebControls.DropDownList
    { 
        protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection)
        {
            if (base.LoadPostData(postDataKey, postCollection))
                return true;

            // this means that the value selected was not present in the .Items collection
            string[] values = postCollection.GetValues(postDataKey);
            if (values == null || values.Length == 0)
                return false;

            // add the value to the Items collection so that it can be processed later on.
            this.Items.Add(new ListItem("Custom value created by JavaScript", values[0]));
            this.SetPostDataSelection(this.Items.Count - 1);
        }
    }
}

Itemsコードによっては、レンダリングする前にこれらのカスタム値をコレクションから削除したい場合があることに注意してください。

.aspxファイルのサンプル:

<%@ Register TagPrefix="my" Namespace="Project.MyWebControls" Assembly="Project" %>
<my:MyDropDownList runat="server" ...></my:MyDropDownList>
于 2013-02-28T11:24:31.200 に答える
1

ViewStateに対して を完全に無効にすることができますDropDownList

<asp:dropdownlist id="abc" runat="server" EnableViewState="false"></asp:dropdownlist>

あなたの質問の更新に:

これにより、質問が大きく変わります。新しい質問への回答は次のとおりです:無効なポストバックまたはコールバック引数。「<pages enableEventValidation="true"/>」を使用してイベントの検証を有効にします

于 2013-02-26T09:52:08.863 に答える
1

わかりました、ここにもう 1 つのオプションがあります。AsyncPostBackTrigger を使用して、これらの項目をリストに追加できます。

いくつかの隠しフィールド:

<asp:TextBox ID="newItemsForAbc" runat="server" style="display:none;"></asp:TextBox>
<asp:TextBox ID="newItemsForDef" runat="server" style="display:none;"></asp:TextBox>
<asp:Button ID="addNewItems" runat="server" OnClick="addNewItems_Click"
  style="display:none;" />

更新パネル:

<asp:UpdatePanel runat="server" ID="UpdatePanel" UpdateMode="Conditional">
   <ContentTemplate>
     <asp:dropdownlist id="abc" runat="server"></asp:dropdownlist>
     <asp:dropdownlist id="def" runat="server"></asp:dropdownlist>
   </ContentTemplate>
   <Triggers>
     <asp:AsyncPostBackTrigger ControlID="addNewItems" EventName="Click" />
   </Triggers>
 </asp:UpdatePanel>

非同期ポストバックを行うための JS 関数:

<script type="text/javascript"> function UpdateStuff(value1, value2)
{
   var abcItems = document.getElementById("<%= newItemsForAbc.ClientID %>");
   var defItems = document.getElementById("<%= newItemsForDef.ClientID %>");
   abcItems.value=value1;
   defItems.value=value2;
   __doPostBack("<%= addNewItems.ClientID %>","");
}
</script>

ボタンのクリックを処理するサーバー側関数:

protected void addNewItems_Click(object sender, EventArgs e)
{
    string[] n1 = newItemsForAbc.Text.Split(';');
    string[] n2 = newItemsForDef.Text.Split(';');

    foreach(string i in n1)
    {
         abc.Items.Add(new ListItem(i, i));
    }

    foreach(string i in n2)
    {
         def.Items.Add(new ListItem(i,i));
    } 
}

リストを更新するには:

var newAbcElements = "Element1;Element2;Element3";
var newDefElements = "Element4;Element5";
UpdateStuff(newAbcElements, newDefElements);

最後の注意: このコードは、そのままでは機能しない可能性があります。新しいアイテムを文字列に格納する方法を変更する必要がある場合があるため、分割/解析も変更されます。リスト項目とその実際の値を表示するために、異なる文字列が必要になることさえあります。しかし、基本的な考え方は理解できると思います。

于 2013-03-05T13:22:45.107 に答える