none
表示されたDropDownList.SelectIndexをVIEWSTATEに格納し、ポストバック後に当該DropDownList.SelectIndexと比較するときまって異なる?! RRS feed

  • 質問

  • 登録済みデータをWebフォームに表示した段階で、全ての表示内容をViewStateに格納するようにしています。

    表示されたデータに対し、ユーザが何か変更を加えたか否かを察知するため、コマンドボタン押下時に、前回の表示項目=ViewStateの内容と 現況の画面コントロールの内容を比較する、という動作を達成中です。

    ところが標題にあるとおり、あるDropDownListがきまって変更されてもいないのに、前回SelectIndexと異なった選択になっていると、察知されます。事実デバッグモードで確認すると、初回データ表示時に ViewStateへ-1(未選択)が格納されていることが背景にあります!!!

    初回データ表示時、画面上のDropDownListへ DB上の選択結果を収める方式はSelctedValueを使用しています。SelectedIndexではありません。

    かたや、変化を確認するためのプロパティはSelectedIndexで行っています。(=ViewStateItemへの保管・比較。これが要因かと思い、SelectedValueで格納&比較するようにすても状況は変わらなかった)

    【質問】

    ポストを一回でも経験すると、当該DropDownListのSelectIndexは0になるのですが、データ表示時SelectedValueを設定しても、これに該当するIndex値がselectedになることはないのでしょうか??

    当該DropDownListの内容は、SQLDataSourceを当該Webフォームに貼り付け、これをデータソースとして生成されています。コードはDB上に記録された登録時の選択結果を画面に反映するための記述です(ロードイベント not Post back時)

    データソースが生成される順序と、Selctedvalueが指定されるタイミングが 微妙なのかなぁ? とこちらに記載しながら、問い合わせすべきか迷う私でした。 

    参考:SQLDatasource内SelectCommnd=SELECT YEAR(GETDATE()) UNION SELECT YEAR(GETDATE())+1

    つまり、今年と来年の4桁 2行が収まるだけ


    • 編集済み saya24 2013年3月2日 6:11
    2013年3月2日 6:09

回答

すべての返信

  • すみません、回答ではありません。

    > 登録済みデータをWebフォームに表示した段階で、全ての表示内容をViewStateに格納するようにしています。

    > 表示されたデータに対し、ユーザが何か変更を加えたか否かを察知するため、コマンドボタン押下時に、
    > 前回の表示項目=ViewStateの内容と 現況の画面コントロールの内容を比較する、という動作を達成中です。

    フレームワークがやってくれていることをもう一度実装しているのはなぜでしょう。。。
    たぶん、もっとフレームワーク、というかこの場合各コントロールの動作かな、それを深く理解して、
    フレームワーク/コントロールをうまく使おうと考えるほうが良いのではないかと思います。


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

    2013年3月2日 11:29
  • > 登録済みデータをWebフォームに表示した段階で、全ての表示内容をViewStateに格納
    > するようにしています。
    >
    > 表示されたデータに対し、ユーザが何か変更を加えたか否かを察知するため、コマン
    > ドボタン押下時に、前回の表示項目=ViewStateの内容と 現況の画面コントロールの
    > 内容を比較する、という動作を達成中です。

    具体的にどうやっているのですか? それがわからないと正しくコーディングされているかわかりません。

    また、目的は何でしょう? それがわかると、そういう方法ではできないけど、こうすればできるというような回答ができるかもしれません。

    それから、小野さんのコメントもよく考えることをお勧めします。

     

    2013年3月2日 22:59
  • 皆様

    いつもご見解をありがとうございます。

    >具体的にどうやっているのですか?

    他画面のGridViewから行選択され、DataNavigateURLForamtSrtingで当画面が表示されるようになっています。

    PageLoadイベント内で not IsPostbackの際に限り

    真っ先にViewState.Clear()

    その後、今回の項目も含め画面上の項目全てに、DBからの内容を収めていきます。表示のためです。

    Dim cnStr As String = System.Configuration.ConfigurationManager.ConnectionStrings("XXX_Con").ConnectionString

            Using connection As New SqlConnection(cnStr)

                Dim command As New SqlCommand(strSQL, connection)
                connection.Open()
                Dim dr As SqlDataReader = command.ExecuteReader
                Do While dr.Read

             DropDownList5.SelectedValue = Left(dr("SHIPMENTYMD"), 4)       ’←問題のDDL
             DropDownList6.SelectedValue = Mid(dr("SHIPMENTYMD"), 5, 2)
             DropDownList7.SelectedValue = Right(dr("SHIPMENTYMD"), 2)

    ....表示ロジック省略

    上記ののち、述べていたように画面の内容をViewState.Itemに格納していきます。(自動で保管されている?!、小野さんのコメントで知りました)

    ViewState.Item("DropDownList5.SelectedIndex") = DropDownList5.SelectedIndex     '出荷日 YY ←問題のDDL
    ViewState.Item("DropDownList6.SelectedIndex") = DropDownList6.SelectedIndex     '出荷日 MM
    ViewState.Item("DropDownList7.SelectedIndex") = DropDownList7.SelectedIndex     '出荷日 DD

    End Sub ということで、PageLoadイベントが終了です。

    この後、ユーザが画面に変更を加えるか否かは表示内容次第です。いずれにせよ、ユーザが表示内容に基づき「承認」の意味をなすコマンドボタン押下で次のサーバー側の動作になります。(まてよ、AutoPostBackをTrueにしている項目があるので、必ずしもそうといえないか??)

    Protected Sub Button6_Click1(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button6.Click

        If ViewState.Item("DropDownList5.SelectedIndex") <> DropDownList5.SelectedIndex Then ’←問題のDDL
               GoTo UnMatch_VS
           End If
            If ViewState.Item("DropDownList6.SelectedIndex") <> DropDownList6.SelectedIndex Then
                GoTo UnMatch_VS
            End If
            If ViewState.Item("DropDownList7.SelectedIndex") <> DropDownList7.SelectedIndex Then
                GoTo UnMatch_VS
            End If

        ~省略

    UnMatch_VS:

        Button6.Visible = False        '承認ボタンは非表示にする
           Button5.Visible = True         '確認ボタンを表す

           AlertMessage = "内容が変更されたので再度確認ボタンを押下して下さい。"
           上記メッセージを表示するコーディング alert('" & AlertMessage & "') 

    End Sub ということで、Button6クリックイベントが終了です。

    DropDownList6とDropDownList7は ポスト後でも変化が生じていないので、これらとの違いが解決の糸口に思いました。

    違いは、DropDownList5のみがSQLDataSourceからデータソースを設定されている点です。SelectCommnd=SELECT YEAR(GETDATE()) UNION SELECT YEAR(GETDATE())+1、つまり、今年と来年の4桁 2行が収まるだけ

    DropDownList6には1~31・DropDownList7に1~12のリストアイテムを、項目の編集画面ListItemコレクションエディタから直接追加しています。

    取り急ぎ、お返事致しました。

    ViewStateについてこれから文献を再確認したいと思います。今まで開発してきたもの全てが同様の対応をしているので、自動で保管されているとのこと...お恥ずかしい限り

    • 編集済み saya24 2013年3月4日 0:30 途中で投稿されてしまいましたので追記です。
    2013年3月3日 23:46
  • 依然としてよく見えないですが、必要のない余計なことをして、おかしなことになっているような感じです。

    ViewState.Clear() など不要だし、SelectedIndex を ViewState に保存する必要もないはずです。

    普通にツールボックスからドラッグ&ドロップして作れば、DropDownList の選択項目がポストバック前後で変更されたときは SelectedIndexChanged イベントが発生するので、そのハンドラで処置すればやりたいことができると思います。

    ListControl.SelectedIndexChanged イベント
    http://msdn.microsoft.com/ja-jp/library/vstudio/system.web.ui.webcontrols.listcontrol.selectedindexchanged%28v=vs.100%29.aspx


    > ViewStateについてこれから文献を再確認したいと思います。

    以下のページがお勧めです。

    ASP.NET のビュー ステートの理解
    http://msdn.microsoft.com/ja-jp/library/ms972976.aspx

    • 回答の候補に設定 佐伯玲 2013年3月6日 4:09
    • 回答としてマーク saya24 2013年3月9日 11:51
    2013年3月4日 12:50
  • 皆様、ご見解をありがとうございました。また暫くの放置申し訳ございませんでした。

    もともとホストコンピューター時代に培った画面設計方針を、ASP.NETを開発する上でも引き継いでしまっている点が、常識外になっているのかも知れません。

    また、AJAX(非同期)の構築については まだまだ手が出ないという点も背景にあります。

    今回開発している画面の牽制といえば、DBサーバー側とのマスタチェックがほぼです。そしてDBサーバーとのやりとりとなれば、基幹のシステムですから そうちくちくと入ってきて欲しくない、

    これが一番、最低限のポストで全ての牽制を行いたい理由ですかね。

    いずれにしても、まだDropDownList5のみ、ViewStateと違いが生じていることは事実ですが、皆様に自分のやり方を説得する自信もなく、常識でないことについて公けの場をお借りするのも申し訳ございませんので本件クローズとしたいと思います。

    SuferOnWww様,ViewStateの文献の紹介ありがとうございました。

    2013年3月9日 12:30