前回は、非常に中途半端なところで終わってしまった。
前回のエントリ:[C#][Silverlight]DataGrid上でのマウスホイールでスクロールさせる方法(挫折)
あれから、暇を見つけてはうまいことホイールスクロールさせる方法を探してたけど満足行く動きをするものは出来ていない。
やってみて駄目だったこと。
- ScrollViewerをDataGridのVisualTreeから取得して、そいつのスクロールバーの位置を変える
→DataGridは、ScrollViewerを内部で使ってなかったのでNG。(ListBoxはこの方法でうまくいった) - 縦方向のScrollBarをDataGridのVisualTreeから取得して、そいつのValueを書き換える
→DataGridは、ScrollBarのScrollイベントを監視して内容の再描画をしているみたいで、Valueプロパティを変えただけではスクロールバーの位置に応じて中身が描き変わってくれなかった。
ということで、とりあえず現状の妥協案は…
ホイールスクロールを検出したらDataGridのSelectedIndexの値をホイールをまわした方向に応じて+1, -1する。
DataGridのSelectedItemに対して、ScrollIntoViewメソッドを呼び出して選択行が画面から外にある場合にスクロールするようにした。
ホイールを回すと選択行が変わってしまうのがExcelと違って気持ち悪いとか言われそうだけど、とりあえずこれしか出来なかったorz
もっといい方法見つけた人は情報Plz。
とりあえず、現状のコード。
いつものPersonクラス。
namespace SilverlightScrollSample
{
public class Person
{
public int ID { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
}
DataGridを置いて、ItemsSourceをBindingしただけのPage.xaml
<UserControl xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" x:Class="SilverlightScrollSample.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid x:Name="LayoutRoot" Background="White">
<data:DataGrid x:Name="dataGrid1" ItemsSource="{Binding}" />
</Grid>
</UserControl>
そして、Page.xaml.cs
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Browser;
using System.Windows.Controls;
namespace SilverlightScrollSample
{
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
#region DataContextの初期化
// とりあえず500件の適当なデータをlistに詰めてDataContextに入れる
// ObservableCollection<T>にT[]やIEnumerable<T>を受け取るコンストラクタが無い!?
var list = new ObservableCollection<Person>();
foreach (var i in Enumerable.Range(1, 500))
{
list.Add(new Person
{
ID = i,
Name = "田中 太郎no" + i,
Age = i % 30 + 10
});
}
DataContext = list;
#endregion
#region スクロールイベントの登録
// スクロール系のイベントハンドラを登録
HtmlPage.Window.AttachEvent("onmousewheel", OnMouseWheelTurned);
HtmlPage.Document.AttachEvent("onmousewheel", OnMouseWheelTurned);
#endregion
}
// ホイールスクロールイベント
private void OnMouseWheelTurned(object sender, HtmlEventArgs e)
{
ScriptObject eventObject = e.EventObject;
// ホイールを手前に回したら +1、奥がわに回したら-1になるように変換(IE限定)
int delta = (int)((double)eventObject.GetProperty("wheelDelta")) / -120;
// 選択行をdeltaぶん変化させた後に、範囲外のIndexにならないように変更
int index = dataGrid1.SelectedIndex + delta;
if (index >= ((ICollection<Person>)DataContext).Count)
{
index = ((ICollection<Person>)DataContext).Count - 1;
}
if (index < 0)
{
index = 0;
}
// 選択行を変更してスクロール
dataGrid1.SelectedIndex = index;
dataGrid1.ScrollIntoView(dataGrid1.SelectedItem, null);
}
}
}
動作は以下のような感じ。
起動して
マウスのホイールをくるくるっと
さらにくるくるっと
とりあえず、これがここ数日の成果。
というか、ホイールでスクロール出来ないっていうのは業務アプリとかだとお客さんに「ちょっとねぇ…」って言われそうな気がする。
そんな時は、こんな感じで逃げる!!