実現したいこと
ListBoxでタッチ(ドラッグ)スクロールができるUserControlを作成したい。
発生している問題・エラーメッセージ
タッチ(ドラッグ)したままListBoxの範囲外にでるとスクロールが反転してしまう。
該当のソースコード
SliderControl.vb
VB.net
1Imports System.ComponentModel 2 3Public Class SliderControl : Implements INotifyPropertyChanged 4 5 6 Public Shared ReadOnly TargetListBoxProperty As DependencyProperty = DependencyProperty.Register("TargetListBox", GetType(ListBox), GetType(SliderControl), New PropertyMetadata(Nothing)) 7 Private WithEvents _ListBox As ListBox 8 Private _Draging As Boolean 9 Private _DragStart As Double 10 Private _StartScrollY As Double 11 Private WithEvents _ScrollViewer As ScrollViewer 12 Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged 13 14 15 Public Property TargetListBox As ListBox 16 Get 17 Return CType(GetValue(TargetListBoxProperty), ListBox) 18 End Get 19 20 Set(value As ListBox) 21 SetValue(TargetListBoxProperty, value) 22 RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("TargetListBox")) 23 End Set 24 End Property 25 26 Private Sub SliderControl_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded 27 _ListBox = TargetListBox 28 _ScrollViewer = GetDescendantsFromVisual(Of ScrollViewer)(_ListBox)(0) 29 End Sub 30 31 32 Private Sub ListBox_PreviewMouseDown(sender As Object, e As MouseButtonEventArgs) Handles _ListBox.PreviewMouseDown 33 _Draging = True 34 SetMousePosition(e.GetPosition(Me)) 35 End Sub 36 37 Private Sub SetMousePosition(p As Point) 38 _DragStart = p.Y 39 _StartScrollY = _ScrollViewer.VerticalOffset 40 End Sub 41 42 Private Sub ListBox_PreviewMouseUp(sender As Object, e As MouseButtonEventArgs) Handles _ListBox.PreviewMouseUp 43 _Draging = False 44 End Sub 45 46 Private Sub OrderListView_PreviewMouseMove(sender As Object, e As MouseEventArgs) Handles _ListBox.PreviewMouseMove 47 If _Draging Then 48 Dim point = e.GetPosition(Me) 49 Dim offset = _DragStart - point.Y 50 Dim current = _StartScrollY + offset 51 Console.WriteLine(current) 52 53 _ScrollViewer.ScrollToVerticalOffset(current) 54 End If 55 End Sub 56 57 Public Shared Function GetDescendantsFromVisual(Of T As {DependencyObject})(obj As DependencyObject) As IEnumerable(Of T) 58 Return Descendants(obj).OfType(Of T) 59 End Function 60 Private Shared Iterator Function Descendants(obj As DependencyObject) As IEnumerable(Of DependencyObject) 61 If obj Is Nothing Then 62 Return 63 End If 64 65 For Each child In Children(obj) 66 Yield child 67 For Each gc In Descendants(child) 68 Yield gc 69 Next 70 Next 71 End Function 72 Private Shared Iterator Function Children(obj As DependencyObject) As IEnumerable(Of DependencyObject) 73 If obj Is Nothing Then 74 Return 75 End If 76 77 Dim count = VisualTreeHelper.GetChildrenCount(obj) 78 If count = 0 Then 79 Return 80 End If 81 82 For i As Integer = 0 To count - 1 83 Dim child = VisualTreeHelper.GetChild(obj, i) 84 If child IsNot Nothing Then 85 Yield child 86 End If 87 Next 88 End Function 89End Class
SliderControl.xaml
WPF
1<UserControl x:Class="SliderControl" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 mc:Ignorable="d" > 7 8</UserControl>
MainWindow.vb
VB.net
1Class MainWindow 2 Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded 3 Dim l As New List(Of String) 4 For i = 0 To 300 5 l.Add(CStr(i)) 6 Next 7 Listbox.ItemsSource = l 8 9 End Sub 10End Class
MainWindow.xaml
VB.net
1<Window x:Class="MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:WpfApp39" 7 mc:Ignorable="d" 8 Title="MainWindow" Height="450" Width="800"> 9 <Grid> 10 <ListBox Name="Listbox" Width="150" Height="300" HorizontalAlignment="Left"></ListBox> 11 <local:SliderControl TargetListBox="{Binding ElementName=Listbox}"/> 12 </Grid> 13</Window>
補足情報(FW/ツールのバージョンなど)
.net4.8 Windows11
TargetListBoxにBindingすると対象のListBoxがタッチスクロールできるというものです。
以下の手順で症状の確認ができます。
・マウスホイールで画面の中央あたりまでスクロールします。
・ListBoxの画面上部をドラッグします。
・そのまま上方向へListBox範囲外になるまでドラッグします。
・ListBoxの範囲外になるとスクロールが反転します。
また上記操作で、ListBox上部の境界線からぎりぎりはみ出たところでドラッグしていると
マウスカーソルを動かしていないのにも関わらず、0.5秒間隔くらいで1行くらい反転してスクロールがされる謎の挙動も発生します。
よろしくお願いいたします。

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2024/05/17 11:58
2024/05/19 23:12 編集
2024/05/20 10:01