VC.NET ~ ListViewの先頭に表示されるアイテムを制御する

前置き

縦スクロールバー付きのListViewで、特定の行を表示領域の先頭に表示させたい場合、その行を選択状態にするだけではダメです。じゃぁ、どうするか、という話し。

サンプルアプリ

ボタンを押すと、スピンに入力された行が先頭に表示されるアプリです。

LVスクロールアプリ

ListViewは、以下のように初期化してあります。

for ( int i = 0; i < 100; i++ ) {
  mLeftView->Items->Add(
    gcnew ListViewItem(
      gcnew array<String^>{
        String::Format("{0:d04}", i + 1), "COL2"}  // 1オリジンで。
    )
  );
}

mLeftViewという名前は気にしないで下さい。後でmRightViewを追加する予定だったので…。

ListView::EnsureVisible()を使う

int targetIX = Convert::ToInt32(mRowSpin->Value - 1);  // 0オリジンで。
mLeftView->EnsureVisible(mLeftView->Items->Count - 1); // ※1
mLeftView->EnsureVisible(targetIX);                    // ※2
mLeftView->Items[targetIX]->Selected = true;

ListView::EnsureVisible(rowIX)は、rowIXで指定された行が、必ず表示領域に収まるように自動スクロールさせるメソッドです。

上記のコードでは、まずリストの最後のアイテムをensureし(※1)、次に所望のアイテムをensureしています(※2)。※2だけでは所望のアイテムが表示領域の先頭に来るとは限らないので、まず※1でリストの一番下までスクロールさせてから、※2とするのが正解です。チラつくのでは? という不安を感じますが大丈夫なようです。

スクロール成功

バグ

ListView::TopItemというプロパティがあるので、これを変更するだけでも良さそうな気がしますが、バグがあるようで、正確にスクロールされない場合があります。

int targetIX = Convert::ToInt32(mRowSpin->Value - 1); // 0オリジンで。
mLeftView->TopItem = mLeftView->Items[targetIX];
mLeftView->Items[targetIX]->Selected = true;

スクロール失敗

ずれてますね。遠くにスクロールするとずれることがあるようです。

Last modified:2011/11/23 13:12:48
Keyword(s):
References:[.NETアプリ開発]
This page is frozen.