前回の記事で書いたとおり、DataGrid上でマウスのホイールをまわしてもスクロールしてくれない。
試した見たところListBoxでも駄目だったので、きっと駄目なんだろう。
ということでググってみると色々情報があった。
それによると、JavaScriptでホイールスクロールを扱うようなコードをC#とかで書くとOKらしい。
(きっとJavaScriptでも無問題)
とりあえずやってみよう
さくっとSilverlightのプロジェクトを作った。名前は、SilverlightScrollSampleにした。テスト用のWebアプリも一緒に作成した。
まずは、いつものPersonクラスを作成する。
namespace SilverlightScrollSample
{
public class Person
{
public int ID { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
}
これの配列をPage.xamlのDataContextに突っ込む。
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
// 適当なデータをlistに詰めてDataContextに入れる
// ObservableCollection<T>にT[]やIEnumerable<T>を受け取るコンストラクタが無い!?
var list = new ObservableCollection<Person>();
foreach (var i in Enumerable.Range(1, 100))
{
list.Add(new Person
{
ID = i,
Name = "田中 太郎no" + i,
Age = i % 30 + 10
});
}
DataContext = list;
}
}
そして、DataGridを画面に置いてItemsSourceにDataContextをバインドする。
<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 ItemsSource="{Binding}" />
</Grid>
</UserControl>
これで、下のように表が表示される。
見た目いい感じ。編集も出来ちゃう。でも、スクロールできないorz
スクロールできるように試行錯誤
これにマウスのホイールでスクロール機能を追加してみようと思う。
(コードをシンプルにするためにIE限定対応でいきます。)
ホイールスクロールに対応するために、System.Windows.Browser.HtmlPageというクラスを使ってHTMLの世界にSilverlightからダイブする。
後は、onmousescrollイベントなんかを登録すれば良いらしい。そして、イベントハンドラでwheelDeltaというプロパティをEventObjectから取得すればいいということだ。
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Windows.Browser;
using System.Windows.Controls;
namespace SilverlightScrollSample
{
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
#region DataContextの初期化
// 省略
#endregion
#region スクロールイベントの登録
// スクロール系のイベントハンドラを登録
HtmlPage.Window.AttachEvent("onmousewheel", OnMouseWheelTurned);
HtmlPage.Document.AttachEvent("onmousewheel", OnMouseWheelTurned);
#endregion
}
private void OnMouseWheelTurned(object sender, HtmlEventArgs e)
{
ScriptObject eventObject = e.EventObject;
// とりあえず確認
Debug.WriteLine(eventObject.GetProperty("wheelDelta"));
}
}
}
この状態でデバッグ実行してマウスホイールのスクロールをやるとデバッガの出力に数字がパラパラと出てくる。
手前にホイールスクロールすると-120で、奥側にスクロールすると+120になるみたいだ。(IEの場合)
ということで、とりあえず120を基準として、なおかつスクロールバー的には手前に回したときに+であってほしいのでマイナスもかけた数字をホイールスクロールの基本値にする。
private void OnMouseWheelTurned(object sender, HtmlEventArgs e)
{
ScriptObject eventObject = e.EventObject;
double delta = ((double)eventObject.GetProperty("wheelDelta")) / -120;
delta *= 150; //150くらいスクロールしたいかな
Debug.WriteLine("##" + delta + "だけスクロールバー動かすよ");
}
わかりにくいけど、ホイールスクロールを一生懸命まわしてる図
後は、スクロールしてやればいいという話しになるんだけど、ListBoxやDataGridにはそういった類のプロパティやメソッドが見当たらない。
ScrollViewerになら、ScrollToVerticalOffsetというそのもののメソッドがあるのに。
ということは、DataGridのVisualTreeを舐めていってScrollViewerをゲットすればいいじゃん?って思ってVisualTreeを舐めていったらScrollViewerが取得できなかった。
なぜだろう??
ListBoxでは、この方法でいけそうだけど…う~ん。
今日は時間切れなので中途半端だけどここまで!
今日のまとめ
JavaScriptと同じ要領でコードを組めば、スクロールの結果を取得することは出来る!!
参考サイト:
http://phpspot.org/blog/archives/2006/08/javascript_23.html
http://silverlight.net/forums/p/12382/39973.aspx
http://www.wintellect.com/cs/blogs/jprosise/archive/2008/03/18/mousewheel-zooms-in-silverlight-2-0.aspx