かずきのBlog

C#やJavaやRubyとメモ書き

目次

Blog 利用状況

ニュース

わんくまBlogが不安定になったため、前に書いてたはてなダイアリーにメインを移動します。
かずきのBlog@Hatena
技術的なネタは、こちらにも、はてなへのリンクという形で掲載しますが、雑多ネタははてなダイアリーだけに掲載することが多いと思います。
コメント
プログラマ的自己紹介
お気に入りのツール/IDE
プロフィール
経歴
広告
アクセサリ

書庫

日記カテゴリ

2008年11月13日 #

[C#][Silverlight]DataGridのマウスホイールでのスクロール その2

前回は、非常に中途半端なところで終わってしまった。
前回のエントリ:[C#][Silverlight]DataGrid上でのマウスホイールでスクロールさせる方法(挫折)

あれから、暇を見つけてはうまいことホイールスクロールさせる方法を探してたけど満足行く動きをするものは出来ていない。
やってみて駄目だったこと。

  1. ScrollViewerをDataGridのVisualTreeから取得して、そいつのスクロールバーの位置を変える
     →DataGridは、ScrollViewerを内部で使ってなかったのでNG。(ListBoxはこの方法でうまくいった)
  2. 縦方向の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);
        }


    }
}

動作は以下のような感じ。

起動して
image

マウスのホイールをくるくるっと
image

さらにくるくるっと
image

とりあえず、これがここ数日の成果。
というか、ホイールでスクロール出来ないっていうのは業務アプリとかだとお客さんに「ちょっとねぇ…」って言われそうな気がする。

そんな時は、こんな感じで逃げる!!

posted @ 1:38 | Feedback (2)

[C#][WPF][Silverlight]ScrollBarコントロールのScrollイベント

まだまだ、マウスホイールでのスクロールの仕方と奮闘中。
ListBoxについては、やり方はわかったが、DataGridのほうがまだわからない。

DataGridのほうのやり方がわかったら、ListBoxともどもBlogに書こうと思う。その調べ物のの過程でわかったことで、知らなかったことがあったのでメモ。

ScrollBarのValueプロパティは、現在のスクロールバーの位置を表している。
なので、このプロパティの値を変えることでスクロールバーの位置を変えることが出来る。

ここで1つ罠というか仕様がある。

Valueプロパティを変更してもScrollイベントが発生しない。

DataGridは、Scrollイベントが発生したときに中身の描画をやりなおしてるっぽくて、VisualTreeからScrollBarを取得してValueを変えるだけでは中身が再描画されなかった。
非常に残念。

誰かDataGridのマウスホイールでのスクロールで、うまいこと成功してる人っているのかな…。

posted @ 0:14 | Feedback (0)