トップ回答者
C# FormViewでTextBoxにSession値をセットできない。

質問
-
FormViewで顧客情報登録のフォームを実装しております。
入力→確認→完了と画面遷移をSessionを使って実装させたいと思っております。①入力画面で「確認画面へボタン」を押下後、入力値をSession情報に格納。
②確認画面で「戻るボタン」を押下後、入力画面で入力値をSession情報から、各TextBoxにセットする。①はうまく実装できたのですが、
②がうまくいきませんでした。
以下のようなエラーとなってしまいます。-----------------------------
▼エラー内容
「NullReferenceExceptionはユーザによってハンドルされませんでした。
オブジェクト参照がオブジェクト インスタンスに設定されていません」どなたかアドバイスを頂けないでしょうか。
以下はDBやソース情報となります。-----------------------------
▼DB情報:顧客テーブル(Customer)
顧客ID:CustomerId
氏名(姓):NameSei
氏名(名):NameMei-----------------------------
▼開発環境
Webアプリケーションです。
.Net Flamework4.0
C#
Visual Studio 2010
SQL Server 2008 R2-----------------------------
▼aspx.cs
namespace WebApplication1
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//①開発デバッグ用として"山田"をSessionに格納する。
Session["Session_NameSeiTextBox"] = "山田";
if (Session["Session_NameSeiTextBox"] != null)
{
((TextBox)FormView1.FindControl("NameSeiTextBox")).Text
= Session["Session_NameSeiTextBox"].ToString();
}
}
}
}
-----------------------------
▼aspx
<asp:FormView ID="FormView1" runat="server" DataKeyNames="Customer"
DataSourceID="SqlDataSource1">
<EditItemTemplate>
氏名(姓):<asp:TextBox ID="NameSeiTextBox" runat="server" Text='<%# Eval("NameSei") %>' /><br />
氏名(名):<asp:TextBox ID="NameMeiTextBox" runat="server" Text='<%# Bind("NameMei") %>' /><br />
顧客Id:<asp:TextBox ID="CustomerIdTextBox" runat="server" Text='<%# Bind("CustomerId") %>' /><br />
<asp:LinkButton ID="UpdateButton" runat="server" CausesValidation="True"
CommandName="Update" Text="更新" />
<asp:LinkButton ID="UpdateCancelButton" runat="server"
CausesValidation="False" CommandName="Cancel" Text="キャンセル" />
<asp:Button ID="Button1" runat="server" onclick="Button1_Click1" Text="確認画面へ" />
</EditItemTemplate>
<InsertItemTemplate>
氏名(姓):<asp:TextBox ID="NameSeiTextBox" runat="server" Text='<%# Eval("NameSei") %>' /><br />
氏名(名):<asp:TextBox ID="NameMeiTextBox" runat="server" Text='<%# Bind("NameMei") %>' /><br />
顧客Id:<asp:TextBox ID="CustomerIdTextBox" runat="server" Text='<%# Bind("CustomerId") %>' /><br />
<asp:LinkButton ID="InsertButton" runat="server" CausesValidation="True"
CommandName="Insert" Text="挿入" />
<asp:LinkButton ID="InsertCancelButton" runat="server"
CausesValidation="False" CommandName="Cancel" Text="キャンセル" />
<asp:Button ID="Button2" runat="server" onclick="Button1_Click1" Text="確認画面へ" />
</InsertItemTemplate>
<ItemTemplate>
氏名(姓):<asp:Label ID="NameSeiLabel" runat="server" Text='<%# Eval("NameSei") %>' /><br />
氏名(名):<asp:Label ID="NameMeiLabel" runat="server" Text='<%# Bind("NameMei") %>' /><br />
顧客Id:<asp:Label ID="CustomerIdLabel" runat="server" Text='<%# Bind("CustomerId") %>' /><br />
<asp:LinkButton ID="EditButton" runat="server" CausesValidation="False"
CommandName="Edit" Text="編集" />
<asp:LinkButton ID="NewButton" runat="server" CausesValidation="False"
CommandName="New" Text="新規作成" />
</ItemTemplate>
</asp:FormView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConflictDetection="CompareAllValues"
ConnectionString="<%$ ConnectionStrings:xxxConnectionString %>"
InsertCommand="INSERT INTO [Customer] ([CustomerId], [NameSei], [NameMei])
VALUES (@CustomerId, @NameSei, @NameMei)"
OldValuesParameterFormatString="original_{0}"
SelectCommand="SELECT * FROM [Customer]"
UpdateCommand="UPDATE [Customer]
SET [NameSei] = @NameSei, [NameMei] = @NameMei, [CustomerId] = @CustomerId
WHERE [CustomerId] = @original_CustomerId
AND (([CustomerId] = @original_CustomerId)
OR ([CustomerId] IS NULL AND @original_CustomerId IS NULL))">
AND (([NameSei] = @original_NameSei)
OR ([NameSei] IS NULL AND @original_NameSei IS NULL))
AND (([NameMei] = @original_NameMei)
OR ([NameMei] IS NULL AND @original_NameMei IS NULL))
<InsertParameters>
<asp:Parameter Name="CustomerId" Type="Int32" />
<asp:Parameter Name="NameSei" Type="String" />
<asp:Parameter Name="NameMei" Type="String" />
</InsertParameters>
<UpdateParameters>
<asp:Parameter Name="NameSei" Type="String" />
<asp:Parameter Name="NameMei" Type="String" />
<asp:Parameter Name="CustomerId" Type="Int32" />
<asp:Parameter Name="original_CustomerId" Type="Int32" />
<asp:Parameter Name="original_NameSei" Type="String" />
<asp:Parameter Name="original_NameMei" Type="String" />
</UpdateParameters>
</asp:SqlDataSource>
</asp:Content>私としては、
if (Session["Session_NameSeiTextBox"] != null)
で、NULL判定をしているにもかかわらず、
((TextBox)FormView1.FindControl("NameSeiTextBox")).Text = Session["Session_NameSeiTextBox"].ToString();
で、NullReferenceExceptionエラーが出てくるのが、分かりません・・・
どなたかご教授頂けないでしょうか?
ちなみに以下のコードとすると、
「名前'NameSeiTextBox'は現在のコンテキスト内に存在しません。」というエラーとなります。
---------------------------------------
protected void Page_Load(object sender, EventArgs e)
{
Session["Session_NameSeiTextBox"] = "山田";
NameSeiTextBox.Text = Session["Session_NameSeiTextBox"].ToString();
}
---------------------------------------それでFindControlを使ってみたのですが、NullReferenceExceptionエラーとなりました・・・
あとは「Page_Load」を「Page_PreRenderComplete」や「ItemCreated」としても、同様の事象でした。
うまくいきません・・・アドバイスをどうぞ宜しくお願い致します。
回答
-
Page_PreRenderComplete なら、FormViewへのデータバインドなども終了しているので、この時点なら間違いないかな。
ただ、FormViewの状態に(InsertやEditじゃない)よってはテキストボックスが存在しないことがありますから、それを考慮する必要があります。あと、FormViewのイベントでタイミングをとることもできるかと。
このほうがFormViewの状態チェックが簡単かなぁ。参考になるような情報はあまりないですね。
自分は、いろんなイベントのメソッドをとりあえず追加して、それにブレークポイントいれて、どの順番でイベントが発生するか、とかそのときのコントロールツリーはどうなっているか、とか確認しました。
あおい情報システム株式会社 小野修司(どっとねっとふぁん)
- 回答としてマーク ミルズ 2012年6月19日 23:36
-
タイミングというよりは、常に "NameSeiTextBox" というコントロールが存在するわけではないことにご注意ください。
NameSeiTextBox は FormView の EditItemTemplate と InsertItemTemplate の中にしか存在しません。
編集と新規作成以外では NameSeiTextBox というコントロールは、どのタイミングで FindControl しても見つからないのだと思います。
FindControl が null を返すことへの考慮が必要なのではないかと思います。- 回答としてマーク ミルズ 2012年6月19日 23:36
すべての返信
-
私としては、
if (Session["Session_NameSeiTextBox"] != null)
で、NULL判定をしているにもかかわらず、
((TextBox)FormView1.FindControl("NameSeiTextBox")).Text = Session["Session_NameSeiTextBox"].ToString();
で、NullReferenceExceptionエラーが出てくるのが、分かりません・・・
どなたかご教授頂けないでしょうか?
ちなみに以下のコードとすると、
「名前'NameSeiTextBox'は現在のコンテキスト内に存在しません。」というエラーとなります。
---------------------------------------
protected void Page_Load(object sender, EventArgs e)
{
Session["Session_NameSeiTextBox"] = "山田";
NameSeiTextBox.Text = Session["Session_NameSeiTextBox"].ToString();
}
---------------------------------------
Session["Session_NameSeiTextBox"] が null なのではなくて、FormView1.FindControl("NameSeiTextBox")) が null を返しているのだと思います。
Null オブジェクトの Text プロパティを参照しようとして、NullReferenceException なのではないかと。
FindControl の件は、別のスレッド で解決済みなのだと思っていたのですが。 -
>totojo様
確かに、TextBoxからSessionへの書き込みは別のスレッドでも以下のように解決しました。
----------------
protected void Button_Session_Student_Click(object sender, EventArgs e)
{
Session["Session_StudentNameSeiTextBox"] = ((TextBox)FormView1.FindControl("StudentNameSeiTextBox")).Text;
}
----------------今回は、逆にSession値をTextBoxにセットしようとしております。
以下のようなコードではダメなのでしょうか?
----------------
protected void Page_Load(object sender, EventArgs e)
{
//①開発デバッグ用として"山田"をSessionに格納する。
Session["Session_NameSeiTextBox"] = "山田";
if (Session["Session_NameSeiTextBox"] != null)
{
((TextBox)FormView1.FindControl("NameSeiTextBox")).Text
= Session["Session_NameSeiTextBox"].ToString();
}
}
----------------
上記の部分でエラーとなります。
「NullReferenceExceptionはユーザによってハンドルされませんでした。
オブジェクト参照がオブジェクト インスタンスに設定されていません」アドバイスお願い出来ますでしょうか。
-
Page_PreRenderComplete なら、FormViewへのデータバインドなども終了しているので、この時点なら間違いないかな。
ただ、FormViewの状態に(InsertやEditじゃない)よってはテキストボックスが存在しないことがありますから、それを考慮する必要があります。あと、FormViewのイベントでタイミングをとることもできるかと。
このほうがFormViewの状態チェックが簡単かなぁ。参考になるような情報はあまりないですね。
自分は、いろんなイベントのメソッドをとりあえず追加して、それにブレークポイントいれて、どの順番でイベントが発生するか、とかそのときのコントロールツリーはどうなっているか、とか確認しました。
あおい情報システム株式会社 小野修司(どっとねっとふぁん)
- 回答としてマーク ミルズ 2012年6月19日 23:36
-
タイミングというよりは、常に "NameSeiTextBox" というコントロールが存在するわけではないことにご注意ください。
NameSeiTextBox は FormView の EditItemTemplate と InsertItemTemplate の中にしか存在しません。
編集と新規作成以外では NameSeiTextBox というコントロールは、どのタイミングで FindControl しても見つからないのだと思います。
FindControl が null を返すことへの考慮が必要なのではないかと思います。- 回答としてマーク ミルズ 2012年6月19日 23:36
-
> FormViewで顧客情報登録のフォームを実装しております。
> 入力→確認→完了と画面遷移をSessionを使って実装させ
> たいと思っております。以前のスレッドで、FormView はそういう目的には向いてな
いとアドバイスしているのに、それを無視して、わざわざ
面倒な方向に進んでいるようです。何故ですか?どうしても FormView を使って、それとは別に確認画面を
表示する必要があるなら、それらは同一ページ実装するこ
とをお勧めします。FormView と確認画面の表示は Panel
で切り替えるか、MultiView を使って View を分けること
で可能です。同一ページに作れば、FormView の TextBox のユーザー入
力は ViewState で自動的に維持されるので、Session を
使う必要はなくなり、このような苦労はせずにすむはずで
す。
なお、今回エラーが出たのはタイミングの問題です。先の
スレッドでも書きましたが、TextBox は動的に生成されま
す。Page.Load イベントの時点では TextBox は存在しない
から FindControl の結果が null になるのです。FormView.ItemCreated イベントのタイミングならうまく行
くと思います。でも、こちらの解決方法に進むのはお勧め
しません。軌道修正して FormView と確認画面を同一ペー
ジに実装することをお勧めします。
#ところで、以下のスレッドが放置常態となっています。
解決したならクローズしてください。DataTextFieldプロパティの連結
http://social.msdn.microsoft.com/Forums/ja-JP/aspnetja/thread/7097007e-c0ce-42d4-96a4-356f15bfa21b -
>小野@どっとねっとふぁん様
>totojo様TextBoxにSession値をセットする事ができました。
ご指摘頂いたように「Page_PreRenderComplete」にした事でセットできました。
(やはりタイミングという事でしたね。)また、nullを返すことへの考慮として、if文でnullチェックをしたり、
確認画面から「戻るボタン」を押下際に、フラグを立てるなどの対策を施しました。
>SurferOnWww様FormViewを使ってフォームを実装しているのは、
Insert・Edit・lyなどの切り替えがしたいが為です。
(確かDetailsViewではそれは出来なかったと思います。)また、MultiViewやPanelでの切り替えも試みたのですが、以前ご指摘頂いたように、
http://social.msdn.microsoft.com/Forums/ja-JP/vwdexpressja/thread/9435683a-40ab-43ca-b66b-bdbc3be28f26
確か、FormViewでのMultiViewの入れ子や、
MultiView配下へのPanelの配置はできないと教えて頂きました。
「'System.Web.UI.WebControls.FormView' には 'Panel' というパブリック プロパティは含まれていません。」おっしゃる通りにFormViewで無理に実装をしているのかもしれませんが、
確認画面が必須要件なので、手段は何でもいいのですが、
色んな方法で手探りながらなんとか実装を試みております。
ご迷惑をお掛けし申し訳ございません。 -
> ご迷惑をお掛けし申し訳ございません。
いえ、私には何も迷惑などかかっていませんので、ご心配な
く。ただ、結果的にできれば何でもいいということで、基本的な
パターンから外れた形で作ってしまうと、後でミルズさんが
作った Web アプリを他の人が保守する場合、保守する人に
は多大な迷惑をかけるかもしれないということは、心に留め
ておいたほうがよさそうです。失礼な言い方かもしれませんが、基本的なところがわかって
ないので、回答者のアドバイスが理解できず、迷走している
という感じです(上のレスを見ても、アドバイスがほとんど
理解されてないのが分ります)。本などで勉強して、基本的な知識をつけることをお勧めしま
す。基本的な知識なしで掲示板でやり取りしていても、話が
通じないので、解決するのは難しいです。- 編集済み SurferOnWww 2012年6月20日 13:40 追記