#setlinebreak(on);
[[WP TIPS に戻る>wp7/tips]]
*ListBox をスクロールさせる [#k4b8e4c7]
サンプルプロジェクト [[Listbox_scroll.zip>https://skydrive.live.com/redir.aspx?cid=793b87c06d2f0cd5&resid=793B87C06D2F0CD5!1911&parid=793B87C06D2F0CD5!223]]
ListBox のスクロール部分は ScrollViewer で実装されており、この ScrollViewer を取り出して、使用することで ListBox に表示されている項目をスクロールさせることが出来ます。
#htmlinsert(u2b,id=c364r6rEhhE,width=480,height=360;)
**ListBox の ScrollViewer を取り出す [#i302b75f]
取り出し方は簡単です。ListBox の最初の子エレメントが ScrollViewer になっているので、VisualTreeHelper.GetChild メソッドで指定すれば取得できます。
private ScrollViewer GetScrollViewer(ListBox lb)
{
return (ScrollViewer)VisualTreeHelper.GetChild(lb, 0);
}
**ListBox をスクロールさせる [#ba029193]
上記の方法で取得した ScrollViewer の ScrollToVerticalOffset メソッドを使用することで、上下にスクロールさせることが出来ます。( ScrollToHorizontalOffset なら左右 )
ScrollToVerticalOffset メソッドに指定する値ですが、通常の ScrollViewer であればピクセルを指定するので 100 を指定すると、左上から 100px の所にスクロールします。
しかし ListBox の ScrollViewer での指定は、表示したい項目のインデックスになります。
たとえば上から10番目の項目を ListBox の先頭に表示させる場合は、9 を指定します。
さらに ScrollToVerticalOffset の値は、double の小数点を指定することが出来、9.5 を指定すると 10番目の項目が半分だけ表示されます(上半分はスクロールしていて隠れる)。
つまり 1つの項目が 1 に相当し、0.1 ずつ足していくと ''項目の高さ 10% ずつ下側にスクロール'' させることが出来ます。逆に 0.1 ずつ引いていくと上側にスクロールします。
DispatcherTimer を使用し 0.1 ずつ変化させると、自動的にスクロールする効果を演出することが出来ます。
private void down_button_Click(object sender, System.EventArgs e)
{
// 現在位置を取得 (表示されている項目のインデックスと等価)
int currentIndex = (int)Math.Floor(this.sv.VerticalOffset);
this.Start(currentIndex + 5);
}
IDisposable q;
private void Start(double to)
{
// 既に動いていたら停止
if (this.q != null)
{
this.q.Dispose();
this.q = null;
}
// 現在位置を取得 (表示されている項目のインデックスと等価)
double from = (int)Math.Floor(this.sv.VerticalOffset);
// タイマで 10ms ごとに、項目の高さ 10% ずつスクロールさせる
double offset = 0.1;
bool isDown = from < to;
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(10);
System.Diagnostics.Debug.WriteLine(from + " " + to);
this.q = Observable.FromEvent<EventArgs>(timer, "Tick")
.Select(n =>
{
from = isDown ? from + offset : from - offset;
return from;
})
.Subscribe(n =>
{
// 範囲を超えたら終了
if (isDown && n > to)
this.q.Dispose();
else if (!isDown && n < to)
this.q.Dispose();
// スクロール
this.sv.ScrollToVerticalOffset(n);
});
// スクロール開始
timer.Start();
}
**スクロール時の注意 [#q6b02838]
上記のように ScrollToVerticalOffset メソッドに 0.1 ずつ値を加算(または減算)することで、なめらかなスクロールを行うことが出来ます。
ただし注意しなければならないのは、''0.1 というのは項目の高さの 10% である'' と言うことです。
たとえば ListBox 最初の項目が 100px の高さの場合 0.1 = 10% = 10px ですが、2番目の項目が 200px の場合 0.1 = 10% = 20px になると言うことです。
高さが違う項目が表示されている場合に 0.1 ずつ足してスクロールさせると、高さの低い項目はゆっくりスクロールし、高い項目は早くスクロールすることになります。
この場合は、各項目の高さを取得し逆算した上で、ScrollToVerticalOffset メソッドに値を設定する必要があります。