1

免責事項:ASP.netページのライフサイクルを読みました。また、動的制御に関するいくつかの 優れた 記事も読みましたが、何かが足りないに違いありません。

背景:私は現在、ユーザーの入力に基づいて多くの動的コンテンツを作成する必要があるWebサイトに取り組んでいます。動的コントロールを永続化し、それらのイベントを正しく接続するには、ポストバックのすべてのページでこれらの動的コントロールを再作成する必要があることを理解しています。

私のプロジェクトの性質上、ユーザーが何を選択したかについての情報がない限り、私のコードは作成するコントロールを認識していません。ユーザーの選択をに保存していますが、まだロードされていないため、ではViewState使用できません。Page_Initしたがって、ViewStateを読み取るまで待つPage_PreLoadPage_Load、読み取ってから、動的コントロールを再作成する必要があります。

わからない部分:の間にコントロールを再作成しようとすると、コントロールはPage_Load保持されますが、関連するイベントが発生しないようです。たとえば、作成したIをクリックしても、ボタン自体は保持されますが、イベントLinkButtonに接続したメソッドは起動されません。Click

偶然に発見した奇妙な解決策は、代わりにコントロールを再作成してPage_PreLoad、イベントが正しく発生するようにすることです。

私の質問(またはむしろ質問):なぜ私の問題は、のPage_PreLoad代わりに私のコントロールを再作成することによって消えるように見えるのPage_Loadですか?これは安全な方法ですか?を使用した他のコードを見たことがないのでPage_PreLoad、注意が必要です。この解決策は私のために働いていますが、私が見逃しているかもしれない落とし穴はありますか?私は無意識のうちに後で失敗する準備をしていますか?

私のコードは、コントロールを作成して静的コントロールLoadDocument()に詰め込むメソッドです。Panel

protected void Page_PreLoad(object sender, EventArgs e)
{
    if (ViewState["xmlfilename"] != null)
    {
        LoadDocument(ViewState["xmlfilename"].ToString());
    }
}
4

2 に答える 2

1

おそらくあなたはこのトピックに関する私の答えの1つを読んだでしょう:

PreLoadイベントを使用した本番環境のコードがあり、正常に機能していることがわかります

しかし、新しい開発のために私はInitイベントを使用しています、なぜですか?これはMicrosoftの推奨事項であり、標準と見なすことができ、ViewStateの自動ロード、テーマのサポート、および最も重要な(私の観点から)などの技術的な利点により、動的制御イベントは同期されます。静的コントロール。

InitViewStateがまだロードされていない場合、あなたの懸念は正しいですが、それでもFormコレクションへのアクセスが停止することはありません。

オンデマンドで動的コントロールを作成する学習目的のページを作成し、Initイベントでそれを実行しています。私は作成TextBoxesしていて、各投稿でTextChanged、テキストが変更されたときにイベントを発生させます。

注:続行する前に、ViewStateがコントロールのIDと一致してロードされることを思い出してください。そのため、同じIDを使用して常に動的コントロールを再作成することをお勧めします。

これはコードです:

ASPX

<asp:HiddenField runat="server" ID="numberOfDynamicControls" Value="0" />
<asp:Panel runat="server" ID="myPanel">
</asp:Panel>
<asp:Button Text="Add Control" runat="server" ID="addControl" OnClick="addControl_Click" />
<asp:Label ID="lblMessage" runat="server" />

ASPXコードビハインド

    protected void Page_Init(object sender, EventArgs e)
    {
        this.CreateDynamicControls();
    }

    protected void addControl_Click(object sender, EventArgs e)
    {
        var n = int.Parse(this.numberOfDynamicControls.Value);
        n++;
        this.numberOfDynamicControls.Value = n.ToString();
        this.myPanel.Controls.Add(this.CreateTextbox(n));
    }

    private void CreateDynamicControls()
    {
        int n = 0;

        if (!string.IsNullOrWhiteSpace(this.Request.Form["numberOfDynamicControls"]))
        {
            n = int.Parse(this.Request.Form["numberOfDynamicControls"]);
        }

        for (int i = 0; i < n; i++)
        {
            var t = this.CreateTextbox(i + 1);
            t.TextChanged += (x, y) => this.lblMessage.Text += "<br/>" + (x as TextBox).ID + " " + (x as TextBox).Text;

            this.myPanel.Controls.Add(t);
        }
    }

    private TextBox CreateTextbox(int index)
    {
        var t = new TextBox { ID = "myTextbox" + index.ToString(), Text = "de" };

        return t;
    }
于 2012-08-01T04:41:37.797 に答える
1

イベントはの間に処理されますProcessPostData。ポストバックをトリガーしたコントロールもポストデータです。その時点でコントロールが存在しない場合、そのコントロールはイベントを受信しません。

Init私は、早すぎて遅すぎることに同意しLoadます。

ここで行う必要があるのは、ビューステートがロードされたらすぐにこれらのコントロールを作成することです。

ページのライフサイクルでは、このためのイベントはありません。ただし、すべての関数は仮想であるため、間に呼び出される関数をオーバーライドできます。

ViewStateに格納されている値に依存するこのようなコントロールをロードするのに最適な場所は、LoadViewState関数です。

  • この関数をオーバーライドします。
  • 最初にbase.LoadViewStateを呼び出すことを忘れないでください。
  • ViewState値に応じてコントロールを作成します。

これで、すべてのコントロールイベントが適切に発生するはずです。

于 2012-08-01T04:20:57.177 に答える