1

バックグラウンド:

JavaScriptで処理されるさまざまなクライアント側のイベントがあるページがあります。これらのイベントの一部をサーバー側のイベントと「同期」するか、コードビハインドから関数を呼び出したいと思います。

JavaScriptで呼び出したい関数の中には、ページにあるフォームのコントロールに変更を加える(たとえば、テキストボックスの値を変更する)場合があります。また、いくつかの値をポストバックを通じて保持したいので、ViewStateに保存したいくつかの値を変更する場合があります。完全なポストバックはしたくありません。更新パネルで変更される可能性のあるコントロールがあります。

私は現在、更新パネルの非同期ポストバックトリガーを介してページの部分的なポストバックをトリガーする非表示のボタンをクリックすることにより、コードビハインドで関数を「呼び出し」ています。

問題:

クライアント側のイベントの1つは、複数の非表示のボタンをクリックするJavaScript関数を呼び出します(クライアント側の処理はクリックの間に発生し、コードビハインド関数の動作に影響を与える可能性があります)。JavaScriptで複数のボタンをクリックすると、ViewStateに加えられた変更が保持されていないように見え、最後のクリックからの変更のみが観察されます。

例:

私はこれをあまりよく説明していなかったかもしれないので、ここに私が持っているものの単純化されたバージョンがあります(私はそれで問題を再現することができます)。

マークアップ:

<asp:Button ID="btnA" runat="server" style="display: none;" />
<asp:Button ID="btnB" runat="server" style="display: none;" />
<div style="background: red; width: 100px; height: 100px;" onclick="AB();"></div>

<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel runat="server" ID="upForm" UpdateMode="Conditional">
    <Triggers>
            <asp:AsyncPostBackTrigger ControlID="btnA" EventName="Click" />
            <asp:AsyncPostBackTrigger ControlID="btnB" EventName="Click" />
    </Triggers>
    <ContentTemplate>
    </ContentTemplate>
</asp:UpdatePanel>

JavaScript:

function AB() {
    $('#<%= btnA.ClientID %>').click();
    $('#<%= btnB.ClientID %>').click();
}

コードビハインド:

Protected Sub btnA_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnA.Click
    ViewState("AB") += "A"
End Sub
Protected Sub btnB_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnB.Click
    ViewState("AB") += "B"
End Sub

質問:

  1. 部分的なポストバック間のViewStateへの変更が失われるのはなぜですか?
  2. 部分的なポストバック間の変更を保存するにはどうすればよいですか?セッション変数はうまく機能しますが、私はそれらを使用することに頼る必要はありません。また、ViewStateでシリアル化されたオブジェクトを実際に変更しているため、非表示のコントロールに値を保存することもできません。
  3. 私がこれを行うことができるより良い方法はおそらくありますか?
4

3 に答える 3

2

これをテストしたところ、部分的なリクエストでビューステートが更新されました。部分的なリクエストが 2 つ連続すると、問題が発生する可能性があります。最初のリクエストは、2 番目のリクエストが機能する前に返される必要があります。

ビューステートが機能する方法は、すべてのリクエストで投稿される __VIEWSTATE という非表示のフィールドがあることです。ASP.NET は、このデータを使用して、必要な状態を維持します。したがって、最初のリクエストがブラウザに返されず、ブラウザでビュー ステートが更新されていない場合、2 番目のリクエストでは送信されません。

更新パネルの応答は次のようになります。

248|updatePanel|ctl00_ContentPlaceHolder1_up|
.......
__VIEWSTATE|/wEPDwUKLTM1OTc4......

ビューステートはクライアント側で更新されます。2 番目のリクエストの前に更新されていることを確認します。

そうは言っても、更新パネルの使用は少し時代遅れだと思います。私があなたなら、javascript と webmetods を使用します。これを見てください。もちろん、それは正確なシナリオに依存します。私の意見では、あなたが使用している方法は汚くて不明確です。

于 2012-06-18T15:57:09.860 に答える
1

Javascript とページのポストバックで 2 つのボタンを「押している」場合、サーバー側のイベント ハンドラーの 1 つだけが登録されるため、クリック イベントの 1 つだけが発生すると思います。

ページ モデルの設計は人間の対話を中心に構築されていると思います。人間はボタンを 1 つしかクリックしないため、サーバー側のクリック イベントは 1 つしか発生できません。あなたの方法は非常に狡猾ですが、基本的に(ボタンを2回押すことで)ページモデルを破壊したため、モデルの動作が停止しました。

頭のてっぺんから外れていますが、私には理にかなっています。

JavaScriptイベントをViewStateタイプの方法で永続化する必要がある場合-独自の永続化メソッドをロールしました。

  1. フォームに隠しフィールドを配置する
  2. JavaScript が実行されると、JSON は保持したいコントロールの状態 (またはオブジェクト) を、意味のあるオブジェクト構造にシリアル化します。
  3. ページがリロードされたら、JavaScript (または JQuery など) を使用して、永続化された JSON 文字列を選択します。オブジェクトに戻し (必要に応じて JSON パーサーまたは eval を使用)、それを使用してページの状態をリセットします。

pageLoad() javaScript メソッドを使用すると、状況に役立つ可能性のある完全なポストバックと部分的なポストバックの両方に対して起動されます。

ちょうど私の経験。あなたに関連/役立つかもしれません

于 2012-06-18T14:53:42.957 に答える
1

私は自分のケースでそれをうまく機能させることができましたが、他のユーザーが提案したオプションのいくつかは私にもうまくいったと思います. 私のケースは非常にユニークなように見えるので (一部はハック方法であるため)、今後の参考のために、この回答に他の提案をいくつか含めました。

  1. JavaScript は 2 つのボタンのクリックをシミュレートしているため、部分的なポストバックが 2 回連続して行われます。最初のリクエストが返される前に 2 番目のリクエストが発生するため、2 番目のサーバー イベントは、最初のイベントから更新された ViewState ではなく、古い ViewState を取得します。

  2. クライアント イベントとサーバー イベントは完全に同期している必要はありません (ユーザーに同期して表示されるだけでよい) ため、コード ビハインド関数を再編成して、クライアント イベントごとに 1 つの部分的なポストバックのみが必要になるようにしました。イベントの流れ。明確にするために、これは実際の解決策というよりも回避策です。

    • Crab Bucketは、JSON オブジェクトを非表示のフォーム フィールドにシリアル化することを提案しました。正確には私が探しているものではありませんが、他の人が同様の問題に遭遇した場合に言及する価値があると思います. 詳細はこちら
  3. ダニエルは、私が (簡単に) 調べたページ メソッドの使用を推奨しましたが、うまくいくようです。この時点で更新パネルから離れて、彼の提案でページを元に戻すには、すでにページにあるもののためにかなりの作業が必要になります. ただし、将来これに戻って試してみる(または別の用途に使用する)かもしれません。jQuery を使用してページ メソッドを呼び出しWeb サービスを利用する方法の詳細。

于 2012-06-18T21:12:44.057 に答える