Skip to content

Commit 8af6429

Browse files
authored
Adding horizontal scroll support (#2640)
Currently this is only being applied to the tab control. However the attached property could be added to any ScrollViewer.
1 parent 5136fd6 commit 8af6429

File tree

2 files changed

+101
-1
lines changed

2 files changed

+101
-1
lines changed

MaterialDesignThemes.Wpf/ScrollViewerAssist.cs

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
using System.Windows;
1+
using System;
2+
using System.Windows;
23
using System.Windows.Controls;
4+
using System.Windows.Interop;
35

46
namespace MaterialDesignThemes.Wpf
57
{
@@ -69,5 +71,102 @@ public static bool GetShowSeparators(DependencyObject element)
6971
public static void SetIgnorePadding(DependencyObject element, bool value) => element.SetValue(IgnorePaddingProperty, value);
7072
public static bool GetIgnorePadding(DependencyObject element) => (bool)element.GetValue(IgnorePaddingProperty);
7173

74+
private static readonly DependencyProperty HorizontalScrollHookProperty = DependencyProperty.RegisterAttached(
75+
"HorizontalScrollHook", typeof(HwndSourceHook), typeof(ScrollViewerAssist), new PropertyMetadata(null));
76+
77+
public static readonly DependencyProperty SupportHorizontalScrollProperty = DependencyProperty.RegisterAttached(
78+
"SupportHorizontalScroll", typeof(bool), typeof(ScrollViewerAssist), new PropertyMetadata(false, OnSupportHorizontalScrollChanged));
79+
80+
private static void OnSupportHorizontalScrollChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
81+
{
82+
//Based on: https://blog.walterlv.com/post/handle-horizontal-scrolling-of-touchpad-en.html
83+
if (d is ScrollViewer scrollViewer)
84+
{
85+
if ((bool)e.NewValue)
86+
{
87+
OnLoaded(scrollViewer, sv =>
88+
{
89+
if (GetSupportHorizontalScroll(sv))
90+
{
91+
RegisterHook(sv);
92+
}
93+
});
94+
}
95+
else
96+
{
97+
OnLoaded(scrollViewer, sv =>
98+
{
99+
if (!GetSupportHorizontalScroll(sv))
100+
{
101+
RemoveHook(sv);
102+
}
103+
});
104+
}
105+
}
106+
107+
static void OnLoaded(ScrollViewer scrollViewer, Action<ScrollViewer> doOnLoaded)
108+
{
109+
if(scrollViewer.IsLoaded)
110+
{
111+
doOnLoaded(scrollViewer);
112+
}
113+
else
114+
{
115+
RoutedEventHandler? onLoaded = null;
116+
onLoaded = (_, _) =>
117+
{
118+
scrollViewer.Loaded -= onLoaded;
119+
doOnLoaded(scrollViewer);
120+
};
121+
scrollViewer.Loaded += onLoaded;
122+
}
123+
}
124+
125+
static void RemoveHook(ScrollViewer scrollViewer)
126+
{
127+
if (scrollViewer.GetValue(HorizontalScrollHookProperty) is HwndSourceHook hook &&
128+
PresentationSource.FromVisual(scrollViewer) is HwndSource source)
129+
{
130+
source.RemoveHook(hook);
131+
scrollViewer.SetValue(HorizontalScrollHookProperty, null);
132+
}
133+
}
134+
135+
static void RegisterHook(ScrollViewer scrollViewer)
136+
{
137+
RemoveHook(scrollViewer);
138+
if (PresentationSource.FromVisual(scrollViewer) is HwndSource source)
139+
{
140+
HwndSourceHook hook = Hook;
141+
scrollViewer.SetValue(HorizontalScrollHookProperty, hook);
142+
source.AddHook(hook);
143+
}
144+
145+
IntPtr Hook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
146+
{
147+
const int WM_MOUSEHWHEEL = 0x020E;
148+
switch (msg)
149+
{
150+
case WM_MOUSEHWHEEL:
151+
int tilt = (short)((wParam.ToInt32() >> 16) & 0xFFFF);
152+
OnMouseTilt(tilt);
153+
return (IntPtr)1;
154+
}
155+
return IntPtr.Zero;
156+
}
157+
158+
void OnMouseTilt(int tilt)
159+
{
160+
scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset + tilt);
161+
}
162+
}
163+
}
164+
165+
public static void SetSupportHorizontalScroll(DependencyObject element, bool value)
166+
=> element.SetValue(SupportHorizontalScrollProperty, value);
167+
168+
public static bool GetSupportHorizontalScroll(DependencyObject element)
169+
=> (bool)element.GetValue(SupportHorizontalScrollProperty);
170+
72171
}
73172
}

MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.TabControl.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
Background="{TemplateBinding wpf:ColorZoneAssist.Background}"
5252
Focusable="False">
5353
<ScrollViewer
54+
wpf:ScrollViewerAssist.SupportHorizontalScroll="True"
5455
HorizontalScrollBarVisibility="Hidden"
5556
VerticalScrollBarVisibility="Hidden">
5657
<StackPanel>

0 commit comments

Comments
 (0)