Created
October 26, 2012 15:03
-
-
Save LeeCampbell/3959289 to your computer and use it in GitHub Desktop.
Corrects the ScrollViewer behavior that does not allow parent to scroll once child has exhausted scrolling.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Windows; | |
using System.Windows.Controls; | |
using System.Windows.Input; | |
using System.Windows.Media; | |
namespace MyLib | |
{ | |
//http://serialseb.blogspot.co.uk/2007/09/wpf-tips-6-preventing-scrollviewer-from.html | |
public sealed class ScrollViewerCorrector | |
{ | |
private static readonly List<MouseWheelEventArgs> ReentrantList = new List<MouseWheelEventArgs>(); | |
public static bool GetFixScrolling(DependencyObject obj) | |
{ | |
return (bool)obj.GetValue(FixScrollingProperty); | |
} | |
public static void SetFixScrolling(DependencyObject obj, bool value) | |
{ | |
obj.SetValue(FixScrollingProperty, value); | |
} | |
public static readonly DependencyProperty FixScrollingProperty = | |
DependencyProperty.RegisterAttached("FixScrolling", typeof(bool), typeof(ScrollViewerCorrector), new FrameworkPropertyMetadata(false, OnFixScrollingPropertyChanged)); | |
public static void OnFixScrollingPropertyChanged(object sender, DependencyPropertyChangedEventArgs e) | |
{ | |
var viewer = sender as ScrollViewer; | |
if (viewer == null) | |
throw new ArgumentException("The dependency property can only be attached to a ScrollViewer", "sender"); | |
var newValue = (bool) e.NewValue; | |
if (newValue) | |
viewer.PreviewMouseWheel += HandlePreviewMouseWheel; | |
else | |
viewer.PreviewMouseWheel -= HandlePreviewMouseWheel; | |
} | |
private static void HandlePreviewMouseWheel(object sender, MouseWheelEventArgs e) | |
{ | |
if (e.Handled) return; | |
var scrollControl = sender as ScrollViewer; | |
if (scrollControl != null && !ReentrantList.Contains(e)) | |
{ | |
var previewEventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta) | |
{ | |
RoutedEvent = UIElement.PreviewMouseWheelEvent, | |
Source = scrollControl | |
}; | |
ReentrantList.Add(previewEventArg); | |
var originalSource = e.OriginalSource as UIElement; | |
if (originalSource != null) | |
originalSource.RaiseEvent(previewEventArg); | |
ReentrantList.Remove(previewEventArg); | |
// at this point if no one else handled the event in our children, we do our job | |
if (!previewEventArg.Handled && | |
( | |
(e.Delta > 0 && scrollControl.VerticalOffset == 0) | |
|| | |
(e.Delta <= 0 && scrollControl.VerticalOffset >= scrollControl.ExtentHeight - scrollControl.ViewportHeight) | |
)) | |
{ | |
e.Handled = true; | |
var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta) {RoutedEvent = UIElement.MouseWheelEvent, Source = scrollControl}; | |
var parent = scrollControl.Parent | |
?? VisualTreeHelper.GetParent(scrollControl); | |
((UIElement)parent).RaiseEvent(eventArg); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment