質問: すごく初歩的な質問かもしれませんが、教えてください。 Visual Web Developer 2008を使用しています。 言語はVBです。 マスターページ:masterpage.master データ表示ページ:datalist.aspx(マスターページはmasterpage.master) マスターページにツリービューがあり、それをクリックすると、データベース内を検索し、該当するものをリストとして表示するのがデータ表示ページになります。 その際の処理として、どのノードがクリックされたかの情報をクエリ文字列にてデータ表示ページに送っていましたが、そうするとポストバックが起きずに、展開されたノードは初期の状態に戻ってしまいます。 抽出したデータを表示させつつも、ツリービューは選択された状態を維持させたいのです。 そこで、いろいろ考えてみたのですが、 1:マスターページに隠しテキストボックスを置き、その中に格納された値を、データ表示ページからFindControlで取得する 2:グローバル変数を使う ただ、グローバル変数が使えるのか、また使用方法等はまだ調べていません。 3:Friend Sharedを使う これはグローバル変数とは違うものなんですかね・・・? いろいろ調べてみたのですが、グローバル変数は宣言する場所がどこなのかわからないという、自分でも情けない状態です。 Friend Sharedの使用方法も微妙です・・・。 隠しテキストボックスを作るやり方は簡単にテストしたらできましたが、極力変数として値を渡す方法でやりたいと思っているので、最終手段にしようと思っています。 目的はノード展開状態の維持なのですが、マスターページからデータ表示ページに値を渡すという流れはそのままでいきたいと思っています。 ポストバック時はノードの展開状態が維持されるとどこかに書いてあったので、ポストバックさせつつ値を渡すのがいいのでは、と思っています。 ご存知の方がいましたら、ヒントでもなんでもいいので教えてください。 足りない情報等は補足いたします。 よろしくお願いします。
回答: 設計手法ですね。 とりあえずポストバックは前提。どうやってデータを引き渡すか、です。 少々難しいステップに来ていると思うので、単純な方法論じゃなく、志向も説明します。解らない言葉は調べてください。アプリケーションスペシャリストとして必要です。 1)マスターページに隠しテキストボックス いかなる場合でも値保持のための「隠しコントロール」はおやめください。後述するFormを使用してください。 2)グローバル変数 .NET自体にグローバル変数はありますが、C#.NETやVB.NETではサポートされません。ですが、共通に参照する「メディエータ」は利用できます。後述します。 3)Friend Sharedを使う 静的変数は、アプリケーションデータスロットの変数です。アプリケーションドメイン内で共通になります。スレッドデータスロットの変数を利用する必要があります。(1アプリケーションドメイン内に複数人のアクセスがあるので、この設計は注意してください)。 staticは排他制御が必要うな場合(ファイルのロックなど)に有効です。 以上の1~3の代替えとしては、Request.Formを利用してください。 RequestインスタンスはPageあるいはHttpContextインスタンスのプロパティとして取得できます。 スレッドデータスロットなので、ポストしてからブラウザにデータが帰るまでの間のデータスロットです。次のポストバックにはまた別になります。 Request.Forms("Data1") = DropDownList1.SelectedValue string value = Request.Forms("Data1") データの代入が、ボタンクリックイベントで行われる場合、それより後のイベントでしかデータ取り出しはできません。うっかりaspxのLoadイベントで取るととれません。PreRenderイベントなどを利用してください。 ------------------- ここからは、オブジェクト指向プログラマとして重要です。 一応言っておきますが、マスターページの中にページがあるように見えますが、実際には逆です。 なので、マスターページで共通機能を持たせる場合、ポストバックはaspxページを意識しない作りになってしまうはずです。 では、どうするか・・・ A)先のグローバル変数のように、何らかの「メディエーター」を使う方法があります。マスターページクラス内に、適当な変数を作成し、ページクラスはそこにデータがあれば、そのデータをもとに処理をする、なければ何もしない、という方法です。マスターページはどのaspxページから参照されるか知る必要はありません。ただ、メディエーターに値を放ります。 aspxページは、マスターページが何をしたか知る必要はありません。Page.MasterPage(キャストしてね).SomeDataBox とかに、検索条件値の値があるかどうかだけをみます。 この方法は、新しいaspxページの追加時に、マスターページを変更しないので拡張性に富みます。 B)参照情報と逆方向のデータの流れなので、「オブザーバー実装パターン」をまず最初に思い浮かべます。 サーチページにインターフェースを持たせ、それをトリガーにする方法です。 ページクラスにISearchPageインターフェースを継承。 ISearchPage インターフェースのメンバーは、 void Search(object data) です。VBなら値を返さないSubです。 マスターページで、自分を参照するページはPageプロパティで取得できますので、そのインスタンスがISearchPageにキャスト可能(これVBだと難しい?)なら、キャストして実行 ((ISearchPage)this.Page).Search (this.DropDownList1.SelectedValue); aspxのページクラスには、検索実行ロジックを書いておきます。 この方法も、検索ページが増えたとしても、ISearchPageを継承していれば、マスターページクラスは変更する必要はなく、拡張性に富んでおります。 思いつく分にはこの二つが代表かと思います。