FlexGrid for WPF
スクロールチップを表示する
基本操作 > スクロール > スクロールチップを表示する

グリッドで垂直スクロールバーのスクロールチップを表示するには、サムをドラッグしたときの行インデックスを取得してスクロールチップにテキストとして表示できます。ユーザーが垂直スクロールバーのサムをドラッグすると、そのトップ行のインデックスはカレントビューポートに入力されます。

たとえば、次のコードでは、グリッドをデータソースと連結していることを前提として、スクロールバーのサムを移動する際にスクロールチップを表示する方法を示します。

【実行例】

コードのコピー
Private Shared _vsb As ScrollBar

Public Sub New()
    InitializeComponent()
    _flex.ItemsSource = Product.GetProducts(100)
End Sub

Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
    Dim scroll As DependencyObject = FindInVisualTreeDown(_flex, GetType(ScrollBar), AddressOf IsVerticalScrollBar)
    _vsb = DirectCast(scroll, ScrollBar)
    AddHandler _vsb.Track.Thumb.MouseLeave, AddressOf Thumb_MouseLeave
    AddHandler _vsb.ValueChanged, AddressOf _vsb_ValueChanged
End Sub

Private Sub Thumb_MouseLeave(sender As Object, e As MouseEventArgs)
    _popup.IsOpen = False
End Sub

Private Sub _vsb_ValueChanged(sender As Object, e As RoutedPropertyChangedEventArgs(Of Double))
    If _vsb.Track.Thumb.IsMouseOver And Mouse.LeftButton = MouseButtonState.Pressed Then
        _popup.IsOpen = True
        Dim p As Point = Mouse.GetPosition(layoutRoot)
        Dim relativePoint As Point = _vsb.TransformToAncestor(layoutRoot).Transform(New Point(0, 0))
        _popup.VerticalOffset = p.Y
        _popup.HorizontalOffset = relativePoint.X
        content.Text = String.Format("Row number is {0}", _flex.ViewRange.TopRow)
    End If
End Sub

Private Function IsVerticalScrollBar(obj As DependencyObject) As Boolean
    Dim scrollbar As ScrollBar = DirectCast(obj, ScrollBar)
    If scrollbar IsNot Nothing Then
        Return scrollbar.Orientation = Orientation.Vertical
    End If
    Return False
End Function

Public Shared Function FindInVisualTreeDown(obj As DependencyObject, type As Type, func As Func(Of DependencyObject, Boolean)) As DependencyObject
    If obj IsNot Nothing Then
        If obj.[GetType]() = type AndAlso func(obj) Then
            Return obj
        End If

        For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(obj) - 1
            Dim childReturn As DependencyObject = FindInVisualTreeDown(VisualTreeHelper.GetChild(obj, i), type, func)
            If childReturn IsNot Nothing Then
                Return childReturn
            End If
        Next
    End If

    Return Nothing
End Function
コードのコピー
public MainWindow()
{
    InitializeComponent();
    this.Loaded += MainWindow_Loaded;
    _flex.ItemsSource = Product.GetProducts(100);
}

ScrollBar _vsb;
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    var scroll = FindInVisualTreeDown(_flex, typeof(ScrollBar), IsVerticalScrollBar);
    _vsb = scroll as ScrollBar;
    _vsb.ValueChanged += _vsb_ValueChanged;
    _vsb.Track.Thumb.MouseLeave += Thumb_MouseLeave;
}

void Thumb_MouseLeave(object sender, MouseEventArgs e)
{
    _popup.IsOpen = false;
}

void _vsb_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    if (_vsb.Track.Thumb.IsMouseOver && Mouse.LeftButton == MouseButtonState.Pressed)
    {
        _popup.IsOpen = true;
        var p = Mouse.GetPosition(layoutRoot);
        Point relativePoint = _vsb.TransformToAncestor(layoutRoot)
                  .Transform(new Point(0, 0));
        _popup.VerticalOffset = p.Y;
        _popup.HorizontalOffset = relativePoint.X;
        content.Text = string.Format("行インデックス:{0}", _flex.ViewRange.TopRow);
    }
}

private bool IsVerticalScrollBar(DependencyObject obj)
{
    var scrollbar = obj as ScrollBar;
    if (scrollbar != null)
    {
        return scrollbar.Orientation == Orientation.Vertical;
    }
    return false;
}

public static DependencyObject FindInVisualTreeDown(DependencyObject obj, Type type, Func<DependencyObject, bool> func)
{
    if (obj != null)
    {
        if (obj.GetType() == type && func(obj))
        {
            return obj;
        }

        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
        {
            DependencyObject childReturn = FindInVisualTreeDown(VisualTreeHelper.GetChild(obj, i), type, func);
            if (childReturn != null)
            {
                return childReturn;
            }
        }
    }

    return null;
}