2

LinkBut​​tonコントロールをPlaceHolderに動的に追加しています。すべてのOnInit()にLinkBut​​tonの新しいインスタンスを追加すると、このLinkBut​​tonのOnClickハンドラーが機能します。

ただし、LinkBut​​tonのインスタンスをセッションに保存し、それをPlaceHolderのコントロールのコレクションに追加すると、LinkBut​​ton.OnClickが起動しません。

特定のシナリオでセッションに保存したコントロールを再利用する方法はありますか?毎回それらを再作成することはほとんどオプションではありません。

補足として、これは1.1で継承されたアプリケーションであり、3.5に移行したばかりです。「壊れた」アプローチは1.1で機能するようでした。

すべての答えをありがとう。

public static void Clicked(object sender, EventArgs e) {
    Debugger.Break();
}

protected override void OnPreInit(EventArgs e) {
    base.OnPreInit(e);
    InitLinkButton();
}

private void InitLinkButton() {    
    var lb = new LinkButton();
    plOne.Controls.Add(lb);
    lb.ID = "lb";
    lb.Text = "I will work.";
    lb.Click += Clicked;
    plOne.Controls.Add(lb);

    LinkButton lb2 = null;
    if (Session["lb2"] == null) {
        lb2 = new LinkButton();
        lb2.ID = "lb2";
        lb2.Text = "I won't work.";
        lb2.Click += Clicked;
        Session["lb2"] = lb2;
    } else {
        lb2 = (LinkButton)Session["lb2"];
    }
    plOne.Controls.Add(lb2);
}
4

4 に答える 4

10

いくつかのこと:

1)WebControlのインスタンスをSessionに保存しないでください。すべてのWebControlには、Pageオブジェクトへの参照があります。もちろん、他のすべてのWebControlを参照します。WebControlをSessionに格納するとすぐに、基本的にページ全体とそれに含まれるすべてのものが保存されます。あなたはメモリリークシティへの高速道路にいます。

2)すべてのコントロールはすべてのポストバックで再作成されます。LinkBut​​tonを毎回再作成するのは遅いと思われるかもしれませんが、そうではありません。

3)ポストバックで動的コントロールを再作成しないのはなぜですか?これは、動的コントロールで行うことになっていることです。全体的な考え方は、ページを以前と同じように設定して、ViewStateをIDに基づいてコントロールに自動的に接続できるようにすることです。Init()の後で動的にページにコントロールを追加しようとすると、ViewStateを使用してコントロールデータを処理できなくなり、独自のメカニズムを実装する必要があります。

Init()で動的コントロールを再作成することをお勧めします。これがベストプラクティスです。

于 2009-05-12T23:53:10.720 に答える
3

OnClickを機能させる方法についての質問に答えるには、イベントをメソッドに接続する必要があります。

lb2.Click += new EventHandler(Clicked);

initのコントロールを再作成することに問題があるのはわかりません。複雑にしすぎないでください!セッションに何を保存するかについては十分に説明されているので、その問題に関する別の回答は投稿しません。

于 2009-05-13T00:05:03.383 に答える
1

また、動的コントロールのプレースホルダーも確認する必要があります。これは、動的コントロールの管理から多くのサルの作業を取り除くのに役立ちます。

于 2009-05-12T23:57:23.910 に答える
1

LinkBut​​tonをセッションに保存するのは本当にひどい考えです。私は、引き起こす可能性のある問題を想像することさえできません。少なくとも、LinkBut​​tonには(Clickedハンドラーを介して)ページへの参照があります。これは実際にはもう存在しないはずです(ページはレンダリングされてクライアントに送信されています)。ただし、参照はそれを存続させるので、GCされません。

そうは言っても、Clickedハンドラーを再配線するだけでよい可能性があります。

if (Session["lb2"] == null) {
    /* ... */
} else {
    lb2 = (LinkButton)Session["lb2"];
    lb2.Click += Clicked;
}

LinkBut​​ton.ClickイベントはPageクラスの別のインスタンス(以前に使用されたもの)に接続されているため、(そのPageは既にレンダリングされているため)起動しても目に見える効果はありません。もちろん、私が上で言ったように、これはまったくの狂気です-それで、私がこれをテストしたようではありません。

これを使用する場合は、GCの問題を回避するために、Page_PreRenderなどで購読を解除する必要があります。

そして、コントロールを再度作成することは、これを行うための通常の方法です-そしてそれは他のすべての人にとって実行可能なオプションなので、あなたはその複雑さを考えすぎているかもしれません。

于 2009-05-12T23:58:11.647 に答える