2009-08-22 23 views
2

次のコードがあります。私は動的に各ステップのコントロールをロードするユーザーコントロールを読み込むインターフェイスのウィザードタイプを作成しようとしています。各ステップにはイベントを発生させるボタンがあります。親ページは、ウィザードで次のコントロールを読み込むことになっています。何が起きているのは、同じコントロールが2回連続してレンダリングされているため、ボタンを2回クリックすることです。ウィザードに動的にロードされたコントロール

コードを見るには別の目が必要です。

public partial class CreateTriviaGame : BasePage 
    { 
     private TriviaGame _game; 
     private int _step = 1; 

     protected void Page_PreLoad(object sender, EventArgs e) 
     { 
      LoadStepControl(); 
     } 

     private void LoadStepControl() 
     {   
      BaseTriviaGameControl ctrl = null; 
      switch (_step) 
      { 
       case 1: 
        ctrl = (BaseTriviaGameControl)LoadControl("AddEditGame.ascx"); 
        break; 
       case 2: 
        ctrl = (BaseTriviaGameControl)LoadControl("CrudQuestions.ascx"); 
        ctrl.TriviaGame = _game; 
        break; 
       case 3: 
        ctrl = (BaseTriviaGameControl)LoadControl("AddEditPaymentInfo.ascx"); 
        ctrl.TriviaGame = _game; 
        break; 
       case 4: 
        ctrl = (BaseTriviaGameControl)LoadControl("ConfirmPayment.ascx"); 
        ctrl.TriviaGame = _game; 
        break; 
       case 5: 
        ctrl = (BaseTriviaGameControl)LoadControl("ThankForPayment.ascx"); 
        ctrl.TriviaGame = _game; 
        break; 
      } 

      ctrl.EntitySaved += new EventHandler(ctrl_EntitySaved); 
      holder1.Controls.Add(ctrl); 

     } 

     protected void ctrl_EntitySaved(object sender, EventArgs e) 
     { 
      _game = ((BaseTriviaGameControl)sender).TriviaGame; 
      _step++; 
      holder1.Controls.Clear(); 
      LoadStepControl(); 
     } 

     protected override void LoadViewState(object savedState) 
     { 
      base.LoadViewState(savedState); 
      _game = (TriviaGame)ViewState["Game"]; 
      _step = (int)ViewState["Step"]; 
     } 

     protected override object SaveViewState() 
     { 
      ViewState["Game"] = _game; 
      ViewState["Step"] = _step; 
      return base.SaveViewState();   
     } 


    } 

** EDIT ** 私はそれらのそれぞれは、前負荷を有する扱う、その後、私はこのようにそれをやっている理由は、宣言のページへのコントロールのすべてを追加することを避けるためであることを追加する必要があります彼らはロードする必要があります。

答えて

1

Page_InitまたはPage_PreInitイベントを使用します。

+0

これらのイベントは使用できません。ビューステートが逆シリアル化される前にそれらは起動します。私はその時点でどんなコントロールを扱っているのか分かりません。 – Darthg8r

+0

また、使用されたプレースホルダもまだ初期化されていません。 – Darthg8r

+0

私もInitCompleteを使ってみました。私はビューステートとプレースホルダーを持っていますが、それでもハンドルを取ることができない振る舞いを持っています。ボタンをクリックすると、ステップ2が表示され、ボタンをクリックすると、ステップ1が表示されます。ボタンをクリックすると、ステップ3が表示されます。ステップ1をクリックします。ステップ4をクリックします。 – Darthg8r

1

この設定はかなり奇妙です。

私が最初に提案したのは、LoadStepControl()の実行中にコントロールにIDを明示的に割り当てることで、コントロールが何であっても同じIDを持つようにすることです。これはおそらくイベントハンドラを失うのに役立ちます。私はあなたがプレースホルダーをクリアし、新しいコントロールを追加すると、イベントハンドラーで推測している、PreLoad()の最初のものが追加されているときとは違うIDをこの方法で取得しています。したがって、IDはポストバック間で一致しないため、イベントハンドラは見つかりません。

私の2番目の提案は、あなたのアプローチを改め、すべてのコントロールをページに静的に追加し、その表示をfalseに設定するだけです。測定可能なパフォーマンスの問題が本当にない限り、これで面倒な手間が省けます。コードの種類があまりにも多くの経験から話しています)

私の3番目の提案はちょうどASP.Net Wizard controlをご覧ください。

+0

動的に追加されたコントロールを扱うときは、それらをページに戻して* Init()イベントの1つでイベントを再配線して、コントロールがイベントサイクル用に存在するようにすることが最善の方法です。 私はまた、物事をオンまたはオフにすることは、おそらく、全面的な再接近が行われない限り行く方法であることに同意します。現在のアプローチでは、ページはすべてのコントロールについて知っていなければならないため、動的にスワップするメリットはありません。コントロール/ステップがデータベースから読み取られている場合は、これが適切です。 –

+0

... HTMLとCSファイルのコントロールを持っているだけで、それらをオフにしても、実際にはオーバーヘッドが発生しない限り、実際のオーバーヘッドは発生しません。 –

1

私はあなたのアプローチについてWompの答えにコメントを付けました。しかし、私がやろうとしていることの完全な文脈を見ていないので、人々が私のアプローチを無視しようとすると、私はそれを個人的に憎む。その場合、あなたの現在のアプローチに可能な解決策をお勧めします。

  1. ページライフサイクルの初期化メソッドで使用できるように、ステップをセッションまたはクエリ文字列に格納します。 viewstateのロードを待つという問題を解決するまで、Wompが引き起こしたイベントの問題を解決することはできません。
  2. 常に、ページのOnInitイベントまたはPreInitイベント中に、各ポストバックでstepの現在の値のプレースホルダにコントロールを追加します。また、今回もイベントを再結線してください。ビューステートがロードされる前に、すべての負荷でこれを行う必要があります。これは、所有者のコントロールが正しく初期化されていることを確認するために不可欠です。
  3. イベントハンドラでこれを行うように、ステップを増やしてコントロールスワップをトリガします(イベントライフサイクルの前に毎回コントロールをページに戻しているため、常に正しく動作します)。

例:最初にページが読み込まれると、AddEditGame.ascxコントロールがホルダーに配置され、OnInit中にイベントが接続されます。ユーザーがポストバックを発生させると、AddEditGame.ascxコントロールがホルダーに再度配置され、イベントを引き起こしたコントロール(AddEditGame.ascx)がイベントサイクルのコントロールツリーに表示されるように、イベントが配線されます。そのイベントが処理されると、ステップを増やしてコントロールスワップをトリガーし、CrudQuestions.ascxをホルダーに入れ、そのイベントを配線します。ユーザーがポストバックを引き起こすと、initなどの間にCrudQuestions.ascxをプレースホルダーに配置します。

最大の変更点は、viewstateがロードされるのを待つことに依存する必要がないことですどのステップを実行しているのかを知るために、イベントサイクルが発生する前にポストバックを発生させたコントロールをページに戻すことで、イベントを正しく発火させることができます。

これは意味がある/助けてくれることを願っています。

関連する問題