トップ回答者
DetailsViewへの値の設定 初期値セット

質問
-
こんにちわ、ASP.net(VB.net)とSQLserverでマスタメンテ画面を作成し始めた初心者です。
件名のようにDetailsViewに初期値を入れておき、入力の手間を省くようにしたいので
下記のような記述をインターネットで見つけたので自分用に項目名のみ変えて追加しました。
DetailsView1を設置した新規登録画面に遷移したときのページロードのコードです。
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Label2.Text = Session("bumon")
Dim tb As TextBox
tb = CType(DetailsView1.FindControl("部門コード"), TextBox)
End Sub
tb.Text = Session("bumon")
tb.Enabled = Falseですが、
NullReferenceException オブジェクト参照がオブジェクト インスタンスに設定されていません。
のエラーが表示されてうまくいきません。デバッグモードで確認したところtbがnothingでした。
うまくキャストできてないような感じですが、これ以上は一人で考えても解らなくなってきたので質問しました。
【解っていること】
・DetailsViewで追加、更新、削除は可能
・SQLserverの項目名は「部門コード」
・Label2.Text = Session("bumon")でログイン時の部門コードを表示できている
・デバッグモードで確認したところtbがnothing
情報が足りないかもしれませんが、すみませんが解る方いましたら、御教授くださいませ。
回答
-
IDは自動的に作成されますが、自動的に作成されたIDを見つけて使用するよりも、自分で明にIDを指定し、それを利用すると良いでしょう。それにはまず、その列をテンプレート列に変換します。
テンプレート列に変換するには、DetailsViewの右上に表示される「>」をクリックし、「フィールドの編集」をクリックして「フィールド」の画面を出します。
「選択されたフィールド」からテンプレートに変換したい列をクリックして選び、「このフィールドをTemplateFieldに変換します」をクリックし、テンプレート列に変換します。その後、OKボタンを押して「フィールド」画面を閉じます。
ふたたび、DetailsViewの右上に表示される「>」をクリックし、今度は「テンプレートの編集」をクリックします。DetailsViewがテンプレート編集モードで開きますので、テンプレート列に変換した列の表示名でInsertItemTemplateを選びます。(もし、表示名を選ぶ画面が出ていない場合は、DetailsViewの右上に表示される「>」をクリックして下さい)
InsertItemTemplate内にTextBoxが表示されます。このTextBoxが新規登録時に表示されます。このTextBoxのプロパティでIDを指定します。これで、TextBoxのIDを明に指定することができました。DetailsViewでFindControlするのはDataBoundイベントで行います。Page.Loadのタイミングではまだ完全にDetailsViewの準備が完了していません。コード例を以下に示します。IDはとりあえずTextBox1にしています。
Protected Sub DetailsView1_DataBound(sender As Object, e As EventArgs) Handles DetailsView1.DataBound If DetailsView1.CurrentMode = DetailsViewMode.Insert Then Dim tb As TextBox tb = CType(DetailsView1.FindControl("TextBox1"), TextBox) tb.Text = Session("bumon") tb.Enabled = False End If End Sub
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 回答としてマーク kureyon77777 2012年8月14日 6:46
すべての返信
-
早速の返信ありがとうございます!
SurferOnWwwさんの御回答で私がわからないことが2つあります。
1.DetailsView1は
Page.Loadのタイミングで作成されている⇒「部門コード」という TextBox ができている
と思っているのですが間違っていますでしょうか?それともIDが間違っているのでしょうか?
2.DetailsViewのInsertモード時、DetailsViewの各項目のTextBoxのIDはどのように調べれば解りますか?
すみませんがよろしくお願い致します。
-
IDは自動的に作成されますが、自動的に作成されたIDを見つけて使用するよりも、自分で明にIDを指定し、それを利用すると良いでしょう。それにはまず、その列をテンプレート列に変換します。
テンプレート列に変換するには、DetailsViewの右上に表示される「>」をクリックし、「フィールドの編集」をクリックして「フィールド」の画面を出します。
「選択されたフィールド」からテンプレートに変換したい列をクリックして選び、「このフィールドをTemplateFieldに変換します」をクリックし、テンプレート列に変換します。その後、OKボタンを押して「フィールド」画面を閉じます。
ふたたび、DetailsViewの右上に表示される「>」をクリックし、今度は「テンプレートの編集」をクリックします。DetailsViewがテンプレート編集モードで開きますので、テンプレート列に変換した列の表示名でInsertItemTemplateを選びます。(もし、表示名を選ぶ画面が出ていない場合は、DetailsViewの右上に表示される「>」をクリックして下さい)
InsertItemTemplate内にTextBoxが表示されます。このTextBoxが新規登録時に表示されます。このTextBoxのプロパティでIDを指定します。これで、TextBoxのIDを明に指定することができました。DetailsViewでFindControlするのはDataBoundイベントで行います。Page.Loadのタイミングではまだ完全にDetailsViewの準備が完了していません。コード例を以下に示します。IDはとりあえずTextBox1にしています。
Protected Sub DetailsView1_DataBound(sender As Object, e As EventArgs) Handles DetailsView1.DataBound If DetailsView1.CurrentMode = DetailsViewMode.Insert Then Dim tb As TextBox tb = CType(DetailsView1.FindControl("TextBox1"), TextBox) tb.Text = Session("bumon") tb.Enabled = False End If End Sub
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 回答としてマーク kureyon77777 2012年8月14日 6:46
-
揚げ足を取っているわけではなくて、正確に書きたいという意図の
みですので、ご了承ください。> IDは自動的に作成されますが、自動的に作成されたIDを見つけて使
> 用するよりも、自分で明にIDを指定し、それを利用すると良いでし
> ょう。それにはまず、その列をテンプレート列に変換します。BoundField を使った場合、自動的に生成される Label や TextBox
に ID は付与されません(null になります)。MSDN ライブラリに "このプロパティが宣言によってもプログラムに
よってもサーバー コントロールに指定されていない場合は、親コン
トロールの Controls プロパティを通じてコントロールへの参照を
取得できます。" と書いてあるように、FindControl を使用しなく
ても TextBox への参照は取得可能です。また、TextBox が生成されるのは DetailsView.ItemCreated イベン
トのタイミングのようです。DataBound イベントは、ポストバックし
て ViewState からデータを取得できる場合は発生しないことがあり
ますので、要注意と思います。 -
揚げ足を取っているわけではなくて、正確に書きたいという意図の
みですので、ご了承ください。忌憚なくどんどんお願いします。
BoundField を使った場合、自動的に生成される Label や TextBox
に ID は付与されません(null になります)。テストコードを書いてみて、自動的にIDが降られていることを確認したのですが、いろいろ調べていくうちに、ClientIDを参照した後だとIDが入っていました。それまではnothingでした。
ClientIDの決定にはIDが必要なようですので、そのタイミングでIDが降られ、たまたま私はそのタイミングでIDを見てしまったようです。Control.ClientID プロパティ
http://msdn.microsoft.com/ja-jp/library/system.web.ui.control.clientidまた、TextBox が生成されるのは DetailsView.ItemCreated イベン
トのタイミングのようです。DataBound イベントは、ポストバックし
て ViewState からデータを取得できる場合は発生しないことがあり
ますので、要注意と思います。今回はTextBoxへの値の設定ですから、おっしゃる通りTextBoxが生成された後に発生するItemCreatedイベントが適切なような気がしますね。
私がDataBoundイベントを選んだ理由は、ItemCreatedイベントハンドラではTextBoxなどのコントロールは生成済みなので取得できますが、そのコントロールのTextプロパティなどの値がまだ取れず、DataBoundイベントハンドラでは取れるため、DataBoundイベントを使うケースが多く、深く考えずにその流れでDataBoundイベントを選んでしまいました。確かにViewStateによって2回目以降はDataBoundイベントが発生しない場合がありますから、注意が必要な場合がありますね。この点については気が付いていませんでした。ご指摘ありがとうございました。★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/