none
ListView.TopItemにListViewItemを代入するとNullReferenceExceptionが発生 RRS feed

  • 質問

  •  

    初めて質問させて頂きます。よろしくお願いします。

     

    開発環境:WindowsVista HomePremium + VB2008Express

     

    ListView(View=Details)をページ単位でスクロールするためのボタンを用意しようと思い、以下のようなソースで実現しようとしています。


    Code Snippet

        Private Sub btnScrollUp_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnScrollUp.Click
            With lvwCodes
                Try
                    .TopItem = .Items(.TopItem.Index - 15)

                Catch ex As Exception
                    .TopItem = .Items(0)
                End Try
            End With
        End Sub

     

        Private Sub btnScrollDown_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnScrollDown.Click
            With lvwCodes
                Try
                    .TopItem = .Items(.TopItem.Index + 15) '←エラー

                Catch ex As Exception
                    .Items(.Items.Count - 1).EnsureVisible()
                End Try
            End With
        End Sub

     

    簡単に言うと、現在ListViewの表示領域にある一番上のアイテム(TopItem)のIndexに、1ページ内に表示できる項目数15を足したアイテムを代入してスクロールさせようとしています。

     

    スクロールアップ(btnScrollUp_Click)は、想定したとおり正常に動きます。

    が、スクロールダウン(btnScrollDown_Click)が、コメントを付けた行で「常に」NullReferenceExceptionが発生します。

     

    これはTopItemプロパティの制限か何かなのでしょうか?

     

    よろしくお願いします。

     

    #ちなみに.NET Frameworkは、事情により2.0を指定しています。

    #ただし、3.5にしても状況は変わりません。

    2008年2月10日 4:23

回答

  • 今度こそ、原因が分りました。

     

    ListView.Item.Addで追加するListViewItemの、Textプロパティが空文字だとこの現象が起きます。

    こんなことで躓いていたとは…これはバグですかね??

     

    とりあえず、ソースベースで簡潔にまとめてみます。

     

    Code Snippet

    Dim Item As ListViewItem

    Item = New ListViewItem

    With Item
        .Text = " " '←Textプロパティには空文字は指定しない。半角スペース1つでもいいから文字を指定すること。
        .Name = "Item1" '←非常に分かり難いが、NameプロパティがKeyと同じもの。(参考まで)
        '.SubItems(0).Text = "" '←これでも、Textプロパティに空文字を入れるのと同じ現象になる。

        '.ImageKey = "" '←イメージリストからイメージを取得しないことを明示する場合、ImageIndexではなくImageKeyに空文字を指定
    End With

    ListView1.Items.Add(Item)

     

     


    以上、今度こそ本当に解決です。

    お騒がせしました。<(_ _)>

    2008年2月10日 17:01

すべての返信

  • 外池です。

     

    ぱっと見た目には大丈夫そうで、私が.TopItem=.Items(ここに直接数値を記述)してみたところ、正常に動きましたし、

    (追記) .TopItem=.Items(.TopItem.Index+15)でも大丈夫でしたし・・・、

     

    試しにですね、NewTopIndex=.TopItemIndex+15を一行前に書いて、.TopItem=.Items(NewTopIndex)ってしみたらどうなります?

    例外が解消されるか、追加した一行でやはりNullReferenceの例外が発生するか。

     

    例外が発生するようであれば、何か別のイベント(お示し頂いたイベントに先立って発生するイベント)で、ListViewの中身を更新する(一度、一斉にクリアするような・・・ .TopItemがNothingになってしまう)ような操作をしていませんか?

     

    2008年2月10日 4:35
  • アドバイス、ありがとうございます。

     

    > NewTopIndex=.TopItemIndex+15を一行前に書いて、.TopItem=.Items(NewTopIndex)って

     

    これは自分でも思ってやってみたんですけど、状況は変わりませんでした。

    やはりTopItemプロパティに代入する時にエラーになります。

    ステップ実行で、行ごとプロパティやの変数の中身を確認しても、中身には正しい値が入っていることを確認しています。

     

    試した方法としては、これ以外に、次にTopItemに代入したいListItemを変数に入れてからそれをTopItemに代入、と言う方法もやりましたが変わりません。

     

    > 例外が発生するようであれば、何か別のイベント(お示し頂いたイベントに先立って発生するイベント)で、ListViewの中身を更新する(一度、一斉にクリアするような・・・ .TopItemがNothingになってしまう)ような操作をしていませんか?

     

    これはしていません。

     

    ちなみに、エラートラップを外して例外の詳細を取得したところ、以下のようになりました。

     

    System.NullReferenceException はハンドルされませんでした。
      Message="オブジェクト参照がオブジェクト インスタンスに設定されていません。"
      Source="System.Windows.Forms"
      StackTrace:
           場所 System.Windows.Forms.ListView.Scroll(Int32 fromLVItem, Int32 toLVItem)    場所 System.Windows.Forms.ListView.set_TopItem(ListViewItem value)    場所 BarCode_1_.frmMain.btnScrollDown_Click(Object sender, EventArgs e) 場所 C:\Users\Yu-ki Satoh\Desktop\バーコード読込アプリ\BarCode\BarCode\frmMain.vb:行 276    場所 System.Windows.Forms.Control.OnClick(EventArgs e)    場所 System.Windows.Forms.Button.OnClick(EventArgs e)    場所 System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)    場所 System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)    場所 System.Windows.Forms.Control.WndProc(Message& m)    場所 System.Windows.Forms.ButtonBase.WndProc(Message& m)    場所 System.Windows.Forms.Button.WndProc(Message& m)    場所 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)    場所 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)    場所 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)    場所 System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)    場所 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)    場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)    場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)    場所 System.Windows.Forms.Application.Run(ApplicationContext context)    場所 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()    場所 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()    場所 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)    場所 BarCode_1_.My.MyApplication.Main(String[] Args) 場所 17d14f5c-a337-4978-8281-53493378c1071.vb:行 81    場所 System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)    場所 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)    場所 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()    場所 System.Threading.ThreadHelper.ThreadStart_Context(Object state)    場所 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)    場所 System.Threading.ThreadHelper.ThreadStart()
      InnerException:

    背景色を設定した箇所が非常に気になるんですが…

    2008年2月10日 11:56
  • あうあう・・・。外池です。例外のメッセージを全部出しちゃうと、いろいろファイル名が見えちゃったりして、大丈夫ですか?

     

    例外の原因は、読ませてもらって、考えてみますが・・・。

     

    2008年2月10日 12:37
  • 外池です。

     

    Debugモードで実行して、例外発生で止まりますよね?

     

    そのときの状況をもっと詳しく調べてみませんか? lvwCodesのItemsプロパティーとTopItemプロパティー、これが、Nothingになっていませんか? ありえないことのように思えますが、NullReferenceの例外が発生するとしたら、これしかないですよね?

     

    しかし、例外発生で、止まる場所が・・・、ListView.Scrollなどという場所だと、ソースコード上には表示されないですね。

     

    例外のSourceがFormということは・・・、もしかして、FormのAutoScrollモードと、lvwCodesと、連動させています?

     

    私の手元では、lvwCodesそのものをNothingにしてみたところ、もちろんNullReferenceが発生するのですが、例外の発生の場所が、ちゃんと、Button_Clickになるので、湯(ゆ)さんとは状況が違うことは明らかです。

     

     

     

     

     

     

    2008年2月10日 13:01
  • 返信ありがとうございます。

    #見られて困る内容はないので大丈夫です。Smile

     

    > Debugモードで実行して、例外発生で止まりますよね?

     

    はい。

     

    >そのときの状況をもっと詳しく調べてみませんか? lvwCodesのItemsプロパティーとTopItemプロパティー、これが、Nothingになっていませんか? ありえないことのように思えますが、NullReferenceの例外が発生するとしたら、これしかないですよね?

     

    はい、これは確認してます。

    前回の内容に書かせていただいたように、TopItemプロパティも、次にTopItemにしたいItemも、Nothingではありません。

     

    > しかし、例外発生で、止まる場所が・・・、ListView.Scrollなどという場所だと、ソースコード上には表示されないですね。

    >

    > 例外のSourceがFormということは・・・、もしかして、FormのAutoScrollモードと、lvwCodesと、連動させています?

     

    特にしていません。

    FormのAutoScrollプロパティも特に変更していません。

     

    > 私の手元では、lvwCodesそのものをNothingにしてみたところ、もちろんNullReferenceが発生するのですが、例外の発生の場所が、ちゃんと、Button_Clickになるので、湯(ゆ)さんとは状況が違うことは明らかです。

     

    ですよね…

    気になるのが、-15は大丈夫なのに+15がダメなところです。

     

    あと、参考になるか分りませんが、NullReferenceが発生した時のListViewの状況をみると、EnsureVisibleメソッドを実行した時と同じスクロール状況になっていることを確認しました。

    2008年2月10日 14:48
  •  湯(ゆ) さんからの引用

    > Debugモードで実行して、例外発生で止まりますよね?

    はい。

     

    このとき、問題の行が黄色い表示で止まります? それともモスグリーンみたいな色?

     

    あとですね・・・、この例外は、必ず発生しますか? それとも、発生することもあるし、発生しないこともある、って感じですか?

    ↑ すいません、愚問でした。「常に」って書いておられますね。ごめんなさい(追記しました。)

     

     

    2008年2月10日 14:57
  •  外池 さんからの引用

    このとき、問題の行が黄色い表示で止まります? それともモスグリーンみたいな色?

     

    Try~Catchを外すと、黄色で止まりますね。

     

     外池 さんからの引用

    あとですね・・・、この例外は、必ず発生しますか? それとも、発生することもあるし、発生しないこともある、って感じですか?

    ↑ すいません、愚問でした。「常に」って書いておられますね。ごめんなさい(追記しました。)

     

    はい、100%の確率です。

    現在の表示位置にも一切関係なく、です。

    2008年2月10日 15:09
  • 外池です。何か共通なものをベースにしないと難しいかもしれません。とりあえず、私の環境で動いているコードを紹介します。単純にForm1にListViewをひとつ貼り付けて、ViewをDetailにしておいて、あと、ボタンを二つ貼り付けました。

     

    で、Form1のコードは以下で全てです。

     

    Code Snippet

    Public Class Form1
        Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
            MyBase.OnLoad(e)
            ListView1.Columns.Add("ID", "ID")

            Dim lvi As ListViewItem
            For I As Integer = 1 To 200
                lvi = New ListViewItem
                lvi.Text = I.ToString
                ListView1.Items.Add(lvi)
            Next

        End Sub

        Private Sub cmdDown_Click(ByVal sender As System.Object, _
                                  ByVal e As System.EventArgs) _
                                 Handles cmdDown.Click
            With ListView1
                Try
                    .TopItem = .Items(.TopItem.Index + 15)
                Catch ex As Exception
                    .Items(.Items.Count - 1).EnsureVisible()
                End Try
            End With
        End Sub

        Private Sub cmdUp_Click(ByVal sender As System.Object, _
                                ByVal e As System.EventArgs) _
                               Handles cmdUp.Click
            With ListView1
                Try
                    .TopItem = .Items(.TopItem.Index - 15)
                Catch ex As Exception
                    .TopItem = .Items(0)
                End Try
            End With
        End Sub
    End Class

     

     

    もし、湯(ゆ)さんのところで、このコードでも例外がでるかどうか・・・。

    2008年2月10日 15:25
  • ご提示いただいたソースを実行してみたところ…正常に動きました。X(

     

    ListViewコントロールも、エラーが起こっているものをコピーして「ListView1」にリネームして実行してみましたが、それでも正常に動きました。X(

     

    んー…何故だろう…

    2008年2月10日 15:40
  • 外池です。

     

    動きましたか・・・。

     

    そうしましたら、まぁ、動くコードから出発して、少しずつ手直ししつつ、湯(ゆ)さんのコードに近づけていってみて、どこでエラーが発生するようになるか・・・、ですね。

     

    いわゆる「問題の切り分け」という作業ですが、根気が要りますが、頑張ってみてください・・・。

     

    ListViewにAddしているListViewItemがどのようなものか・・・、差し支えなければ、教えていただけませんか?

     

    2008年2月10日 15:47
  • ListViewItemを(当然ですが)動的に追加しているので、もしかしたらその部分で何か関係がある個所があるのではないかとコードを見直してみたところ、原因の場所が特定できました。

     

    ListViewにItemを追加する際に、以下のように書いていました。

     

    Code Snippet

    Dim Item As ListViewItem

    'Addメソッドの引数:(key, text, imageIndex)

    Item = ListView1.Items.Add(Code, "", 0)

     

     


    これを、以下のように変更したところ正常に動きました。

     

    Code Snippet

    'Addメソッドの引数:(text, imageKey)

    Item = ListView1.Items.Add("", "")

     

    ※ListViewItemのTextプロパティは、わざと空にしています。

    ※ImageListとは連結していません。

     

    何か、すごく気持ち悪いですが…とりあえずListViewItemのキーは使っていない(というか、使えない?)ので、この方法で対処したいと思います。

     

    ご協力頂き、ありがとうございます。<(_ _)>

    2008年2月10日 15:54
  • 大変申し訳ありません…

    動いたと思ったのが、実は「キチンとは」動いていませんでした。

     

    NullReferenceExceptionは出なくなったのですが、15行分スクロールしなければいけないところが、EnsureVisibleの結果と同じ状態(2行分しかスクロールしない)にしかなりません。

     

    もうちょっと、原因となるコードの特定をしてみます…困ったもんです。

    2008年2月10日 16:12
  • 今度こそ、原因が分りました。

     

    ListView.Item.Addで追加するListViewItemの、Textプロパティが空文字だとこの現象が起きます。

    こんなことで躓いていたとは…これはバグですかね??

     

    とりあえず、ソースベースで簡潔にまとめてみます。

     

    Code Snippet

    Dim Item As ListViewItem

    Item = New ListViewItem

    With Item
        .Text = " " '←Textプロパティには空文字は指定しない。半角スペース1つでもいいから文字を指定すること。
        .Name = "Item1" '←非常に分かり難いが、NameプロパティがKeyと同じもの。(参考まで)
        '.SubItems(0).Text = "" '←これでも、Textプロパティに空文字を入れるのと同じ現象になる。

        '.ImageKey = "" '←イメージリストからイメージを取得しないことを明示する場合、ImageIndexではなくImageKeyに空文字を指定
    End With

    ListView1.Items.Add(Item)

     

     


    以上、今度こそ本当に解決です。

    お騒がせしました。<(_ _)>

    2008年2月10日 17:01
  • 外池です。昨晩は途中で休んでしまってすいませんでした。

     

    私の環境でも現象(例外の発生とその状況)を再現できました。で、すいません、湯(ゆ)さんの、もともとのエラーの原因は、ListViewItemのTextプロパティーが空文字だから、ではありません。ImageIndexに非負の数値(ゼロ以上の数値)を代入してあったからです。

     

    Code Snippet
                lvi = New ListViewItem
                'lvi.Text = ""
                'lvi.ImageIndex = 0
                ListView1.Items.Add(lvi)

     

     

    私の環境で動いたプログラムの一部をこのように修正した上で、コメントアウトを解除する行を変えながら試してみたところ、ImageIndexの設定をコメントアウトしたまま、Textプロパティーに""を代入しても、Nothingを代入しても、例外は発生しませんでした。しかし、ImageIndexにゼロを代入したら、まったく同じ状況で例外が発生しました。

     

    ImageIndexについてドキュメントを見ると、表示させたいImageのSmallImageList(ListViewコントロールのプロパティ)でのインデックスを指定するものであり、既定値はマイナス1となっています。ゼロを入れてしまうと、SmallImageListの最初のImageを指してしまうことになり、SmallImageListが設定されていない(Nothing)ならば例外が発生しても当然と言えるでしょう。(ただ、Upのときに例外で、Downのときに何もおきないのは、不思議ではあります。) 既定値のマイナス1の意味は、Imageを表示させない、ではなくて、ImageIndexは使わない、という意味です。マイナス1を入れておいても、次のImageKeyを使えばImageを表示しようとするからです。

     

    ImageKeyも、空文字を設定しておけば、ImageKeyを使わない、という意味です。Imageを表示させない、という意味には直結しません。で、同様にImageKeyが空文字でも、上述のImageIndexがゼロ以上であればImageを表示しようとするからです。

     

    というわけで、Imageを使わないことを明示的に示すならば、ImageIndexを-1に、かつ、ImageIndexを空文字にセットしなければならないという結論になりますが・・・・、実は、どちらか一方で十分のようです。

     

    ImageIndexに値(マイナス1でも)を代入する操作をすれば、そのとき自動的にImageIndexは空文字になります。

    また、ImageIndexに文字(空文字でも)を代入する操作をすれば、そのとき自動的にImageIndexはマイナス1になります。

     

    そんなわけで、湯(ゆ)さんの最初のプログラムで最小の修正で動くようにするためには、ListViewItemのコンストラクタに渡していたImageIndexのゼロの値をマイナス1にしておけばOKのハズです。
    2008年2月10日 23:29
  • 詳細ありがとうございます。

     

     外池 さんからの引用
    そんなわけで、湯(ゆ)さんの最初のプログラムで最小の修正で動くようにするためには、ListViewItemのコンストラクタに渡していたImageIndexのゼロの値をマイナス1にしておけばOKのハズです。

     

    この修正を試したところ、一瞬上手く動いたように見えたので一度書き込み(11 2 2008, 12:54 午前)をしました。

    ListView1.Items.Add("")、もしくはListView1.Items.Add("", "")にすれば例外は発生しなくなりました。

     

    ただ、例外は発生しなくなったものの、TopItemに入るはずのIndexに15を足したItemが正しく入らず、以下のようになってしまったのです。

    TopItemがIndex=0だとした場合、

    ListView1.TopItem = ListView1.Items(ListView1.TopItem.Index + 15)

    この結果が、ListView1.TopItem.Index = 2になってしまいました。

    これが(11 2 2008, 1:12 午前)の書き込みです。

     

    この状態から更に、ListView1.Items.Add(" ")、もしくはListView1.Items.Add(" ", "")にすれば、

    TopItemがIndex=0だとした場合、

    ListView1.TopItem = ListView1.Items(ListView1.TopItem.Index + 15)

    この結果が正しくListView1.TopItem.Index = 15になりました。

     

    こんな状態でしたが、私の環境以外でも発生する現象なんでしょうか…

    2008年2月12日 19:26
  • 外池です。なーーーんと! 私もフォローが拙速でした。申し訳ありません。仰っていること、理解できました。

     

    私の方でも再現しました。imageIndexだけに気をとられていて気づかなかったのですが、textが空文字だと

    >TopItemがIndex=0だとした場合、

    >ListView1.TopItem = ListView1.Items(ListView1.TopItem.Index + 15)

    >この結果が、ListView1.TopItem.Index = 2になってしまいました。

    になりました。

     

    まぁ、スクロール時のNullReference例外はimageIndexが原因であった。imageを使わないのであれば、imageIndexはマイナス1にしておくこと。これが、ひとつ。

     

    あと、スクロールの動作を正常にしたければ、textは空文字にするな。最低でも空白文字を入れておけ。(普通はtextに何か文字を入れておかないと表示がわけわからなくなりますから、これは良しとすべきじゃないでしょうか)

    2008年2月12日 22:08
  • 外池です。TopItemの指定についてのみに注目してやってみましたが・・・、

     

    ListViewItemのtextに具体的な文字列を入れて、imageIndexをマイナス1にした場合でも、

       ListView1.TopItem = ListView1.Items(ListVie1.TopItem.Index+ n)

    の操作を行った場合に、nで指定した値で狙ったアイテムが、必ずトップに来るとは限りませんね・・・。nが小さな値の場合は、だいたい狙ったとおりになるようですが、nが少し大きくなると(私の環境では、n >= 7)微妙にズレが生じました。一つ先のアイテムがトップに来てしまうのです。

     

    これでは、「ページ」ごとのスクロールをしているつもりでも、過剰な量のスクロール動作で、表示されないまま過ぎてしまうアイテムが出てしまうことになります・・・。

     

    で、改めてドキュメントを読むと、このような動作が許容されているようにも読み取れる記述になっていて、狙ったアイテムがかならず表示されるようにしたければ、EnsureVisibleを使え、ということのようです。

     

    で、これを使おうかな? と思っても、困ってしまいました。スクロール動作前の表示の状態においてギリギリ隠れてしまっているアイテムがどれなのか? indexを得る方法がなさそうです。

     

    こうなると、本来の湯(ゆ)さんの意図された動作を実現するには、表示漏れのアイテムが出ないような少なめのスクロール量を試行錯誤の上で「経験的」に得るしかないのか? と、悲観的になってきました。ListView1にはスクロールバーが一緒に表示されるわけですが、スライダのグリップから外れた場所をクリックすれば、一応、ページごとのスクロールはするんですけど・・・。

     

     

     

     

    2008年2月13日 0:42
  • かなり、自己満足の世界にはいっていますが、外池です。

     

    私なりの結論ですが・・・、「.TopItemへの代入を用いて、スクロールを制御する」ことを、意図したとおりの動きを実現しようとすれば、.TopItemをひとつずつずらす操作を目標のItemを指すまで繰り返すしかないようです・・・。(複数行を一気に動こうとすると、1行ずれる現象の原因は、不明なままです・・・)

     

    で、ページ単位のスクロールを「一番下に見えているItemをトップにもってくる、あるいは、トップに見えているItemを一番下に見える位置にもってくる」として、ちょいと書いてみました。なお、これは、ListViewそのものの大きさや、個々のItemの表示の大きさには依存しないはずです・・・。ListViewのViewはDetailであることが前提です。

     

    Code Snippet

        Private Sub cmdUp_Click(ByVal sender As System.Object, _
                                ByVal e As System.EventArgs) _
                               Handles cmdUp.Click
            With ListView1
                Dim Bottom As Integer = .ClientSize.Height - 1
                Dim TargetItem As ListViewItem = .GetItemAt(0, Bottom)
                If TargetItem Is Nothing Then Exit Sub

                .BeginUpdate()
                Do
                    .TopItem = .Items(.TopItem.Index + 1)
                Loop Until .GetItemAt(0, Bottom) Is Nothing _
                           OrElse .TopItem Is TargetItem
                .EndUpdate()
            End With
        End Sub

        Private Sub cmdDown_Click(ByVal sender As System.Object, _
                                  ByVal e As System.EventArgs) _
                                 Handles cmdDown.Click
            With ListView1
                Dim Bottom As Integer = .ClientSize.Height - 1
                If .TopItem.Index = 0 Then Exit Sub
                Dim TargetItem As ListViewItem = .TopItem

                .BeginUpdate()
                Do Until .TopItem.Index = 0 _
                         OrElse .GetItemAt(0, Bottom) Is TargetItem
                    .TopItem = .Items(.TopItem.Index - 1)
                Loop
                .EndUpdate()
            End With
        End Sub

     

     

     

     

    2008年2月13日 1:49
  • 湯です。

    すみません、ちょっと忙しくてこちら確認するの忘れてました。<(_ _)>

     

    いろいろと検証ありがとうございます。

    本来は、ボタンをクリックすることで「スクロールバーの、スライダがない個所をクリックしたときの動き」を再現させられればベストだったのですが、ListViewにScrollのようなメソッドがないのと、ゴリゴリ作り込まねばならないほどの機能ではなかったので、今回のTopItemで逃げた、と言うのが正直なところです。

     

    特定の条件で、自分の環境以外でも同じことが起こることが分かって、ちょっと安心しました。

    ListViewItem.Textが空文字なのは、CheckBoxを使うから、とか、いくつかの理由が関係しています。

    確かに、一般常識レベルで考えればListViewItem.Textを空にする状況と言うのは、そうあるものではないので、無視してもいいかも知れないですね。

     

    > ListViewItemのtextに具体的な文字列を入れて、imageIndexをマイナス1にした場合でも、

    >    ListView1.TopItem = ListView1.Items(ListVie1.TopItem.Index+ n)

    > の操作を行った場合に、nで指定した値で狙ったアイテムが、必ずトップに来るとは限りませんね・・・。nが小さな値の場合は、だいたい狙ったとおりになるようですが、nが少し大きくなると(私の環境では、n >= 7)微妙にズレが生じました。一つ先のアイテムがトップに来てしまうのです。

     

    こちらの内容もちょっと気になりますが、厳密に1ページ分をスクロールさせなければいけない担保は不要なので、とりあえずは現状の動きでも許容範囲内です。

     

    しかし提示いただいたコードも(いい意味で)きになるので、後で試してみます。

    ありがとうございました。

    2008年2月14日 18:09
  • 外池です。

     

     湯(ゆ) さんからの引用

    本来は、ボタンをクリックすることで「スクロールバーの、スライダがない個所をクリックしたときの動き」を再現させられればベストだった

     

     湯(ゆ) さんからの引用

    ListViewItem.Textが空文字なのは、CheckBoxを使うから、とか、いくつかの理由が関係しています。

     

    実のところ、Textが空文字だから発生しているのかどうかは、私もよくわかりません。私が検証している範囲でTextが空文字の場合は、本当に「真っ白」で、各アイテムが「透明人間」で、で、スクロールバーだけが不気味に動いているような状況でした。ですので、各アイテムが真っ白に表示されているサイズが、非常に小さくなっていて、スクロール巾の制御も言うことを聞かないのかな、とも推測しています。

     

     湯(ゆ) さんからの引用

    厳密に1ページ分をスクロールさせなければいけない担保は不要なので、

     

    ですよね・・・。ただ「見落とす」アイテムが出ることは、許容できないと思いますので・・・、そこだけが注意点かな、と。

     

    私も、相当に勉強になりました。
    2008年2月14日 23:56