none
C# FormViewでTextBoxにSession値をセットできない。 RRS feed

  • 質問

  • 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="更新" />
                    &nbsp;<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="挿入" />
                    &nbsp;<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="編集" />
                    &nbsp;<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」としても、同様の事象でした。
    うまくいきません・・・

    アドバイスをどうぞ宜しくお願い致します。

    2012年6月19日 1:16

回答

  • Page_PreRenderComplete なら、FormViewへのデータバインドなども終了しているので、この時点なら間違いないかな。
    ただ、FormViewの状態に(InsertやEditじゃない)よってはテキストボックスが存在しないことがありますから、それを考慮する必要があります。

    あと、FormViewのイベントでタイミングをとることもできるかと。
    このほうがFormViewの状態チェックが簡単かなぁ。

    参考になるような情報はあまりないですね。
    自分は、いろんなイベントのメソッドをとりあえず追加して、それにブレークポイントいれて、どの順番でイベントが発生するか、とかそのときのコントロールツリーはどうなっているか、とか確認しました。


    あおい情報システム株式会社 小野修司(どっとねっとふぁん)

    • 回答としてマーク ミルズ 2012年6月19日 23:36
    2012年6月19日 9:08
  • タイミングというよりは、常に "NameSeiTextBox" というコントロールが存在するわけではないことにご注意ください。

    NameSeiTextBox は FormView の EditItemTemplate と InsertItemTemplate の中にしか存在しません。
    編集と新規作成以外では NameSeiTextBox というコントロールは、どのタイミングで FindControl しても見つからないのだと思います。
    FindControl が null を返すことへの考慮が必要なのではないかと思います。
    • 回答としてマーク ミルズ 2012年6月19日 23:36
    2012年6月19日 9:16

すべての返信

  • 私としては、
     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 の件は、別のスレッド で解決済みなのだと思っていたのですが。
    2012年6月19日 1:47
  • >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はユーザによってハンドルされませんでした。
    オブジェクト参照がオブジェクト インスタンスに設定されていません」

    アドバイスお願い出来ますでしょうか。

    2012年6月19日 4:22
  • タイミングの問題じゃないかな。
    Page_LoadではFormViewはまだ内部のコントロールとか生成してないはずなので、その時点でテキストボックスは存在していないはず。
    Page_Loadに入ったところでブレークポイントで処理とめて、コントロールの状態を細かく確認してみてください。

     


    あおい情報システム株式会社 小野修司(どっとねっとふぁん)

    2012年6月19日 5:22
  • すいません。タイミングと言われると、
    初心者の私には以下のような発想しか思いつかず・・・
    特に思いつくものが他にありません・・・

    Page_Load、Page_Unit、Page_PreRender、Page_PreRenderComplete

    何か参考となる情報はありますでしょうか?

    2012年6月19日 7:31
  • Page_PreRenderComplete なら、FormViewへのデータバインドなども終了しているので、この時点なら間違いないかな。
    ただ、FormViewの状態に(InsertやEditじゃない)よってはテキストボックスが存在しないことがありますから、それを考慮する必要があります。

    あと、FormViewのイベントでタイミングをとることもできるかと。
    このほうがFormViewの状態チェックが簡単かなぁ。

    参考になるような情報はあまりないですね。
    自分は、いろんなイベントのメソッドをとりあえず追加して、それにブレークポイントいれて、どの順番でイベントが発生するか、とかそのときのコントロールツリーはどうなっているか、とか確認しました。


    あおい情報システム株式会社 小野修司(どっとねっとふぁん)

    • 回答としてマーク ミルズ 2012年6月19日 23:36
    2012年6月19日 9:08
  • タイミングというよりは、常に "NameSeiTextBox" というコントロールが存在するわけではないことにご注意ください。

    NameSeiTextBox は FormView の EditItemTemplate と InsertItemTemplate の中にしか存在しません。
    編集と新規作成以外では NameSeiTextBox というコントロールは、どのタイミングで FindControl しても見つからないのだと思います。
    FindControl が null を返すことへの考慮が必要なのではないかと思います。
    • 回答としてマーク ミルズ 2012年6月19日 23:36
    2012年6月19日 9:16
  • > 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

    2012年6月19日 11:29
  • >小野@どっとねっとふぁん様
    >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で無理に実装をしているのかもしれませんが、
    確認画面が必須要件なので、手段は何でもいいのですが、
    色んな方法で手探りながらなんとか実装を試みております。
    ご迷惑をお掛けし申し訳ございません。 

    2012年6月19日 23:35
  • > ご迷惑をお掛けし申し訳ございません。

    いえ、私には何も迷惑などかかっていませんので、ご心配な
    く。

    ただ、結果的にできれば何でもいいということで、基本的な
    パターンから外れた形で作ってしまうと、後でミルズさんが
    作った Web アプリを他の人が保守する場合、保守する人に
    は多大な迷惑をかけるかもしれないということは、心に留め
    ておいたほうがよさそうです。

    失礼な言い方かもしれませんが、基本的なところがわかって
    ないので、回答者のアドバイスが理解できず、迷走している
    という感じです(上のレスを見ても、アドバイスがほとんど
    理解されてないのが分ります)。

    本などで勉強して、基本的な知識をつけることをお勧めしま
    す。基本的な知識なしで掲示板でやり取りしていても、話が
    通じないので、解決するのは難しいです。


    • 編集済み SurferOnWww 2012年6月20日 13:40 追記
    2012年6月20日 13:39