@@ -64,9 +64,6 @@ public static PaddingMode GetPaddingMode(DependencyObject element)
6464 private static readonly DependencyProperty HorizontalScrollHookProperty = DependencyProperty . RegisterAttached (
6565 "HorizontalScrollHook" , typeof ( HwndSourceHook ) , typeof ( ScrollViewerAssist ) , new PropertyMetadata ( null ) ) ;
6666
67- private static readonly DependencyProperty HorizontalScrollSourceProperty = DependencyProperty . RegisterAttached (
68- "HorizontalScrollSource" , typeof ( HwndSource ) , typeof ( ScrollViewerAssist ) , new PropertyMetadata ( null ) ) ;
69-
7067 private static readonly DependencyProperty BubbleVerticalScrollHookProperty = DependencyProperty . RegisterAttached (
7168 "BubbleVerticalScrollHook" , typeof ( HwndSourceHook ) , typeof ( ScrollViewerAssist ) , new PropertyMetadata ( null ) ) ;
7269
@@ -76,16 +73,16 @@ public static PaddingMode GetPaddingMode(DependencyObject element)
7673 private static void OnSupportHorizontalScrollChanged ( DependencyObject d , DependencyPropertyChangedEventArgs e )
7774 {
7875 //Based on: https://blog.walterlv.com/post/handle-horizontal-scrolling-of-touchpad-en.html
79- if ( d is ScrollViewer scrollViewer )
76+ if ( d is ScrollViewer sv )
8077 {
81- if ( scrollViewer . IsLoaded )
78+ if ( sv . IsLoaded )
8279 {
83- DoOnLoaded ( scrollViewer ) ;
80+ DoOnLoaded ( sv ) ;
8481 }
8582 else
8683 {
87- WeakEventManager < ScrollViewer , RoutedEventArgs > . AddHandler ( scrollViewer , nameof ( ScrollViewer . Loaded ) , OnLoaded ) ;
88- WeakEventManager < ScrollViewer , RoutedEventArgs > . AddHandler ( scrollViewer , nameof ( ScrollViewer . Unloaded ) , OnUnloaded ) ;
84+ RegisterForLoadedEvent ( sv ) ;
85+ RegisterForUnloadedEvent ( sv ) ;
8986 }
9087 }
9188
@@ -97,10 +94,35 @@ static void OnLoaded(object? sender, RoutedEventArgs e)
9794 }
9895 }
9996
97+ static void UnregisterForLoadedEvent ( ScrollViewer sv )
98+ {
99+ WeakEventManager < ScrollViewer , RoutedEventArgs > . RemoveHandler ( sv , nameof ( ScrollViewer . Loaded ) , OnLoaded ) ;
100+ }
101+
102+ static void RegisterForLoadedEvent ( ScrollViewer sv )
103+ {
104+ // Avoid double registrations
105+ UnregisterForLoadedEvent ( sv ) ;
106+ WeakEventManager < ScrollViewer , RoutedEventArgs > . AddHandler ( sv , nameof ( ScrollViewer . Loaded ) , OnLoaded ) ;
107+ }
108+
109+ static void UnregisterForUnloadedEvent ( ScrollViewer sv )
110+ {
111+ WeakEventManager < ScrollViewer , RoutedEventArgs > . RemoveHandler ( sv , nameof ( ScrollViewer . Unloaded ) , OnUnloaded ) ;
112+ }
113+
114+ static void RegisterForUnloadedEvent ( ScrollViewer sv )
115+ {
116+ // Avoid double registrations
117+ UnregisterForUnloadedEvent ( sv ) ;
118+ WeakEventManager < ScrollViewer , RoutedEventArgs > . AddHandler ( sv , nameof ( ScrollViewer . Unloaded ) , OnUnloaded ) ;
119+ }
120+
100121 static void DoOnLoaded ( ScrollViewer sv )
101122 {
102123 if ( GetSupportHorizontalScroll ( sv ) )
103124 {
125+ RegisterForUnloadedEvent ( sv ) ;
104126 RegisterHook ( sv ) ;
105127 }
106128 else
@@ -117,30 +139,23 @@ static void OnUnloaded(object? sender, RoutedEventArgs e)
117139 }
118140 }
119141
120- static void RemoveHandlers ( ScrollViewer scrollViewer )
121- {
122- WeakEventManager < ScrollViewer , RoutedEventArgs > . RemoveHandler ( scrollViewer , nameof ( ScrollViewer . Loaded ) , OnLoaded ) ;
123- WeakEventManager < ScrollViewer , RoutedEventArgs > . RemoveHandler ( scrollViewer , nameof ( ScrollViewer . Unloaded ) , OnUnloaded ) ;
124- }
125-
126- static void RemoveHook ( ScrollViewer scrollViewer )
142+ static void RemoveHook ( ScrollViewer sv )
127143 {
128- if ( scrollViewer . GetValue ( HorizontalScrollHookProperty ) is HwndSourceHook hook &&
129- scrollViewer . GetValue ( HorizontalScrollSourceProperty ) is HwndSource source )
144+ var source = PresentationSource . FromVisual ( sv ) as HwndSource ;
145+ if ( source is not null && sv . GetValue ( HorizontalScrollHookProperty ) is HwndSourceHook hook )
130146 {
131147 source . RemoveHook ( hook ) ;
132- scrollViewer . SetValue ( HorizontalScrollHookProperty , null ) ;
148+ sv . SetValue ( HorizontalScrollHookProperty , null ) ;
133149 }
134150 }
135151
136- static void RegisterHook ( ScrollViewer scrollViewer )
152+ static void RegisterHook ( ScrollViewer sv )
137153 {
138- RemoveHook ( scrollViewer ) ;
139- if ( PresentationSource . FromVisual ( scrollViewer ) is HwndSource source )
154+ RemoveHook ( sv ) ;
155+ if ( PresentationSource . FromVisual ( sv ) is HwndSource source )
140156 {
141157 HwndSourceHook hook = Hook ;
142- scrollViewer . SetValue ( HorizontalScrollSourceProperty , source ) ;
143- scrollViewer . SetValue ( HorizontalScrollHookProperty , hook ) ;
158+ sv . SetValue ( HorizontalScrollHookProperty , hook ) ;
144159 source . AddHook ( hook ) ;
145160 }
146161
@@ -151,15 +166,15 @@ IntPtr Hook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled
151166 const int WM_NCDESTROY = 0x0082 ;
152167 switch ( msg )
153168 {
154- case WM_MOUSEHWHEEL when scrollViewer . IsMouseOver :
169+ case WM_MOUSEHWHEEL when sv . IsMouseOver :
155170 int tilt = ( short ) ( ( wParam . ToInt64 ( ) >> 16 ) & 0xFFFF ) ;
156- scrollViewer . ScrollToHorizontalOffset ( scrollViewer . HorizontalOffset + tilt ) ;
171+ sv . ScrollToHorizontalOffset ( sv . HorizontalOffset + tilt ) ;
157172 return ( IntPtr ) 1 ;
158173 case WM_DESTROY :
159174 case WM_NCDESTROY :
160- RemoveHandlers ( scrollViewer ) ;
161- var source = PresentationSource . FromVisual ( scrollViewer ) as HwndSource ;
162- source ? . RemoveHook ( Hook ) ;
175+ UnregisterForLoadedEvent ( sv ) ;
176+ UnregisterForUnloadedEvent ( sv ) ;
177+ RemoveHook ( sv ) ;
163178 break ;
164179 }
165180 return IntPtr . Zero ;
0 commit comments