|
|
@ -3,29 +3,41 @@ using System.Collections.Generic; |
|
|
|
using System.Diagnostics; |
|
|
|
using System.Diagnostics; |
|
|
|
using System.Linq; |
|
|
|
using System.Linq; |
|
|
|
using System.Reflection; |
|
|
|
using System.Reflection; |
|
|
|
|
|
|
|
using System.Runtime.CompilerServices; |
|
|
|
using System.Text; |
|
|
|
using System.Text; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using System.Windows; |
|
|
|
using System.Windows; |
|
|
|
using System.Windows.Controls; |
|
|
|
using System.Windows.Controls; |
|
|
|
using System.Windows.Controls.Primitives; |
|
|
|
using System.Windows.Controls.Primitives; |
|
|
|
using System.Windows.Data; |
|
|
|
|
|
|
|
using System.Windows.Documents; |
|
|
|
|
|
|
|
using System.Windows.Input; |
|
|
|
using System.Windows.Input; |
|
|
|
using System.Windows.Interop; |
|
|
|
|
|
|
|
using System.Windows.Media; |
|
|
|
|
|
|
|
using System.Windows.Media.Animation; |
|
|
|
using System.Windows.Media.Animation; |
|
|
|
using System.Windows.Media.Imaging; |
|
|
|
|
|
|
|
using System.Windows.Navigation; |
|
|
|
|
|
|
|
using System.Windows.Shapes; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace EleCho.WpfSuite |
|
|
|
using TomsToolbox.Wpf; |
|
|
|
|
|
|
|
using TomsToolbox.Wpf.Interactivity; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace LibScrollingOptimization |
|
|
|
{ |
|
|
|
{ |
|
|
|
/// <inheritdoc/>
|
|
|
|
/// <summary>
|
|
|
|
public class ScrollViewer : System.Windows.Controls.ScrollViewer |
|
|
|
///
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
public class SmoothScrollingBehavior : FrameworkElementBehavior<Control> |
|
|
|
{ |
|
|
|
{ |
|
|
|
static ScrollViewer() |
|
|
|
private ScrollViewer? _scrollViewer; |
|
|
|
|
|
|
|
private ScrollContentPresenter? _scrollContentPresenter; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private delegate bool GetBool(ScrollViewer scrollViewer); |
|
|
|
|
|
|
|
private static readonly GetBool _propertyHandlesMouseWheelScrollingGetter; |
|
|
|
|
|
|
|
private static readonly IEasingFunction _scrollingAnimationEase = new CubicEase() { EasingMode = EasingMode.EaseOut }; |
|
|
|
|
|
|
|
private const long _millisecondsBetweenTouchpadScrolling = 100; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private bool _animationRunning = false; |
|
|
|
|
|
|
|
private int _lastScrollDelta = 0; |
|
|
|
|
|
|
|
private int _lastVerticalScrollingDelta = 0; |
|
|
|
|
|
|
|
private int _lastHorizontalScrollingDelta = 0; |
|
|
|
|
|
|
|
private long _lastScrollingTick; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static SmoothScrollingBehavior() |
|
|
|
{ |
|
|
|
{ |
|
|
|
DefaultStyleKeyProperty.OverrideMetadata(typeof(ScrollViewer), new FrameworkPropertyMetadata(typeof(ScrollViewer))); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if NETCOREAPP
|
|
|
|
#if NETCOREAPP
|
|
|
|
_propertyHandlesMouseWheelScrollingGetter = typeof(ScrollViewer) |
|
|
|
_propertyHandlesMouseWheelScrollingGetter = typeof(ScrollViewer) |
|
|
@ -40,42 +52,67 @@ namespace EleCho.WpfSuite |
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private delegate bool GetBool(ScrollViewer scrollViewer); |
|
|
|
[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "get_ScrollInfo")] |
|
|
|
private static readonly GetBool _propertyHandlesMouseWheelScrollingGetter; |
|
|
|
static extern IScrollInfo GetScrollInfo(ScrollViewer scrollViewer); |
|
|
|
private static readonly IEasingFunction _scrollingAnimationEase = new CubicEase() { EasingMode = EasingMode.EaseOut }; |
|
|
|
|
|
|
|
private const long _millisecondsBetweenTouchpadScrolling = 100; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private bool _animationRunning = false; |
|
|
|
/// <inheritdoc />
|
|
|
|
private int _lastScrollDelta = 0; |
|
|
|
protected override void OnAssociatedObjectLoaded() |
|
|
|
private int _lastVerticalScrollingDelta = 0; |
|
|
|
{ |
|
|
|
private int _lastHorizontalScrollingDelta = 0; |
|
|
|
base.OnAssociatedObjectLoaded(); |
|
|
|
private long _lastScrollingTick; |
|
|
|
|
|
|
|
|
|
|
|
_scrollViewer = AssociatedObject.VisualDescendantsAndSelf().OfType<ScrollViewer>().FirstOrDefault(); |
|
|
|
|
|
|
|
|
|
|
|
private FrameworkElement? _scrollContentPresenter; |
|
|
|
if (_scrollViewer == null) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_scrollViewer.PreviewMouseWheel += ScrollViewer_PreviewMouseWheel; |
|
|
|
|
|
|
|
_scrollContentPresenter = _scrollViewer.VisualDescendants().OfType<ScrollContentPresenter>().FirstOrDefault(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
/// <inheritdoc />
|
|
|
|
public override void OnApplyTemplate() |
|
|
|
protected override void OnAssociatedObjectUnloaded() |
|
|
|
{ |
|
|
|
{ |
|
|
|
base.OnApplyTemplate(); |
|
|
|
base.OnAssociatedObjectUnloaded(); |
|
|
|
|
|
|
|
|
|
|
|
_scrollContentPresenter = GetTemplateChild("PART_ScrollContentPresenter") as FrameworkElement; |
|
|
|
if (_scrollViewer == null) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_scrollViewer.PreviewMouseWheel -= ScrollViewer_PreviewMouseWheel; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (!ScrollWithWheelDelta) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Debug.WriteLine(e.Delta); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CoreScrollWithWheelDelta(e); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void CoreScrollWithWheelDelta(MouseWheelEventArgs e) |
|
|
|
private void CoreScrollWithWheelDelta(MouseWheelEventArgs e) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
if (_scrollViewer == null || _scrollContentPresenter == null) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
if (e.Handled) |
|
|
|
if (e.Handled) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!AlwaysHandleMouseWheelScrolling && |
|
|
|
if (!AlwaysHandleMouseWheelScrolling && |
|
|
|
!_propertyHandlesMouseWheelScrollingGetter.Invoke(this)) |
|
|
|
!_propertyHandlesMouseWheelScrollingGetter.Invoke(_scrollViewer)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool vertical = ExtentHeight > 0; |
|
|
|
bool vertical = _scrollViewer.ExtentHeight > 0; |
|
|
|
bool horizontal = ExtentWidth > 0; |
|
|
|
bool horizontal = _scrollViewer.ExtentWidth > 0; |
|
|
|
|
|
|
|
|
|
|
|
var tickCount = Environment.TickCount; |
|
|
|
var tickCount = Environment.TickCount; |
|
|
|
var isTouchpadScrolling = |
|
|
|
var isTouchpadScrolling = |
|
|
@ -99,31 +136,31 @@ namespace EleCho.WpfSuite |
|
|
|
|
|
|
|
|
|
|
|
if (vertical) |
|
|
|
if (vertical) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (ScrollInfo is IScrollInfo scrollInfo) |
|
|
|
if (GetScrollInfo(_scrollViewer) is IScrollInfo scrollInfo) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// 考虑到 VirtualizingPanel 可能是虚拟的大小, 所以这里需要校正 Delta
|
|
|
|
// 考虑到 VirtualizingPanel 可能是虚拟的大小, 所以这里需要校正 Delta
|
|
|
|
scrollDelta *= scrollInfo.ViewportHeight / (_scrollContentPresenter?.ActualHeight ?? ActualHeight); |
|
|
|
scrollDelta *= scrollInfo.ViewportHeight / (_scrollContentPresenter?.ActualHeight ?? _scrollViewer.ActualHeight); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var sameDirectionAsLast = Math.Sign(e.Delta) == Math.Sign(_lastVerticalScrollingDelta); |
|
|
|
var sameDirectionAsLast = Math.Sign(e.Delta) == Math.Sign(_lastVerticalScrollingDelta); |
|
|
|
var nowOffset = sameDirectionAsLast && _animationRunning ? VerticalOffsetTarget : VerticalOffset; |
|
|
|
var nowOffset = sameDirectionAsLast && _animationRunning ? VerticalOffsetTarget : _scrollViewer.VerticalOffset; |
|
|
|
var newOffset = nowOffset - scrollDelta; |
|
|
|
var newOffset = nowOffset - scrollDelta; |
|
|
|
|
|
|
|
|
|
|
|
if (newOffset < 0) |
|
|
|
if (newOffset < 0) |
|
|
|
newOffset = 0; |
|
|
|
newOffset = 0; |
|
|
|
if (newOffset > ScrollableHeight) |
|
|
|
if (newOffset > _scrollViewer.ScrollableHeight) |
|
|
|
newOffset = ScrollableHeight; |
|
|
|
newOffset = _scrollViewer.ScrollableHeight; |
|
|
|
|
|
|
|
|
|
|
|
SetValue(VerticalOffsetTargetPropertyKey, newOffset); |
|
|
|
SetValue(VerticalOffsetTargetPropertyKey, newOffset); |
|
|
|
BeginAnimation(ScrollViewerUtils.VerticalOffsetProperty, null); |
|
|
|
_scrollViewer.BeginAnimation(ScrollViewerUtils.VerticalOffsetProperty, null); |
|
|
|
|
|
|
|
|
|
|
|
if (!EnableScrollingAnimation || isTouchpadScrolling) |
|
|
|
if (!EnableScrollingAnimation || isTouchpadScrolling) |
|
|
|
{ |
|
|
|
{ |
|
|
|
ScrollToVerticalOffset(newOffset); |
|
|
|
_scrollViewer.ScrollToVerticalOffset(newOffset); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
var diff = newOffset - VerticalOffset; |
|
|
|
var diff = newOffset - _scrollViewer.VerticalOffset; |
|
|
|
var absDiff = Math.Abs(diff); |
|
|
|
var absDiff = Math.Abs(diff); |
|
|
|
var duration = ScrollingAnimationDuration; |
|
|
|
var duration = ScrollingAnimationDuration; |
|
|
|
if (absDiff < Mouse.MouseWheelDeltaForOneLine) |
|
|
|
if (absDiff < Mouse.MouseWheelDeltaForOneLine) |
|
|
@ -134,45 +171,45 @@ namespace EleCho.WpfSuite |
|
|
|
DoubleAnimation doubleAnimation = new DoubleAnimation() { |
|
|
|
DoubleAnimation doubleAnimation = new DoubleAnimation() { |
|
|
|
EasingFunction = _scrollingAnimationEase, |
|
|
|
EasingFunction = _scrollingAnimationEase, |
|
|
|
Duration = duration, |
|
|
|
Duration = duration, |
|
|
|
From = VerticalOffset, |
|
|
|
From = _scrollViewer.VerticalOffset, |
|
|
|
To = newOffset, |
|
|
|
To = newOffset, |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
doubleAnimation.Completed += DoubleAnimation_Completed; |
|
|
|
doubleAnimation.Completed += DoubleAnimation_Completed; |
|
|
|
|
|
|
|
|
|
|
|
_animationRunning = true; |
|
|
|
_animationRunning = true; |
|
|
|
BeginAnimation(ScrollViewerUtils.VerticalOffsetProperty, doubleAnimation, HandoffBehavior.SnapshotAndReplace); |
|
|
|
_scrollViewer.BeginAnimation(ScrollViewerUtils.VerticalOffsetProperty, doubleAnimation, HandoffBehavior.SnapshotAndReplace); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_lastVerticalScrollingDelta = e.Delta; |
|
|
|
_lastVerticalScrollingDelta = e.Delta; |
|
|
|
} |
|
|
|
} |
|
|
|
else if (horizontal) |
|
|
|
else if (horizontal) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (ScrollInfo is IScrollInfo scrollInfo) |
|
|
|
if (GetScrollInfo(_scrollViewer) is IScrollInfo scrollInfo) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// 考虑到 VirtualizingPanel 可能是虚拟的大小, 所以这里需要校正 Delta
|
|
|
|
// 考虑到 VirtualizingPanel 可能是虚拟的大小, 所以这里需要校正 Delta
|
|
|
|
scrollDelta *= scrollInfo.ViewportWidth / (_scrollContentPresenter?.ActualWidth ?? ActualWidth); |
|
|
|
scrollDelta *= scrollInfo.ViewportWidth / (_scrollContentPresenter?.ActualWidth ?? _scrollViewer.ActualWidth); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var sameDirectionAsLast = Math.Sign(e.Delta) == Math.Sign(_lastHorizontalScrollingDelta); |
|
|
|
var sameDirectionAsLast = Math.Sign(e.Delta) == Math.Sign(_lastHorizontalScrollingDelta); |
|
|
|
var nowOffset = sameDirectionAsLast && _animationRunning ? HorizontalOffsetTarget : HorizontalOffset; |
|
|
|
var nowOffset = sameDirectionAsLast && _animationRunning ? HorizontalOffsetTarget : _scrollViewer.HorizontalOffset; |
|
|
|
var newOffset = nowOffset - scrollDelta; |
|
|
|
var newOffset = nowOffset - scrollDelta; |
|
|
|
|
|
|
|
|
|
|
|
if (newOffset < 0) |
|
|
|
if (newOffset < 0) |
|
|
|
newOffset = 0; |
|
|
|
newOffset = 0; |
|
|
|
if (newOffset > ScrollableWidth) |
|
|
|
if (newOffset > _scrollViewer.ScrollableWidth) |
|
|
|
newOffset = ScrollableWidth; |
|
|
|
newOffset = _scrollViewer.ScrollableWidth; |
|
|
|
|
|
|
|
|
|
|
|
SetValue(HorizontalOffsetTargetPropertyKey, newOffset); |
|
|
|
SetValue(HorizontalOffsetTargetPropertyKey, newOffset); |
|
|
|
BeginAnimation(ScrollViewerUtils.HorizontalOffsetProperty, null); |
|
|
|
_scrollViewer.BeginAnimation(ScrollViewerUtils.HorizontalOffsetProperty, null); |
|
|
|
|
|
|
|
|
|
|
|
if (!EnableScrollingAnimation || isTouchpadScrolling) |
|
|
|
if (!EnableScrollingAnimation || isTouchpadScrolling) |
|
|
|
{ |
|
|
|
{ |
|
|
|
ScrollToHorizontalOffset(newOffset); |
|
|
|
_scrollViewer.ScrollToHorizontalOffset(newOffset); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
var diff = newOffset - HorizontalOffset; |
|
|
|
var diff = newOffset - _scrollViewer.HorizontalOffset; |
|
|
|
var absDiff = Math.Abs(diff); |
|
|
|
var absDiff = Math.Abs(diff); |
|
|
|
var duration = ScrollingAnimationDuration; |
|
|
|
var duration = ScrollingAnimationDuration; |
|
|
|
if (absDiff < Mouse.MouseWheelDeltaForOneLine) |
|
|
|
if (absDiff < Mouse.MouseWheelDeltaForOneLine) |
|
|
@ -183,14 +220,14 @@ namespace EleCho.WpfSuite |
|
|
|
DoubleAnimation doubleAnimation = new DoubleAnimation() { |
|
|
|
DoubleAnimation doubleAnimation = new DoubleAnimation() { |
|
|
|
EasingFunction = _scrollingAnimationEase, |
|
|
|
EasingFunction = _scrollingAnimationEase, |
|
|
|
Duration = duration, |
|
|
|
Duration = duration, |
|
|
|
From = HorizontalOffset, |
|
|
|
From = _scrollViewer.HorizontalOffset, |
|
|
|
To = newOffset, |
|
|
|
To = newOffset, |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
doubleAnimation.Completed += DoubleAnimation_Completed; |
|
|
|
doubleAnimation.Completed += DoubleAnimation_Completed; |
|
|
|
|
|
|
|
|
|
|
|
_animationRunning = true; |
|
|
|
_animationRunning = true; |
|
|
|
BeginAnimation(ScrollViewerUtils.HorizontalOffsetProperty, doubleAnimation, HandoffBehavior.SnapshotAndReplace); |
|
|
|
_scrollViewer.BeginAnimation(ScrollViewerUtils.HorizontalOffsetProperty, doubleAnimation, HandoffBehavior.SnapshotAndReplace); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_lastHorizontalScrollingDelta = e.Delta; |
|
|
|
_lastHorizontalScrollingDelta = e.Delta; |
|
|
@ -207,21 +244,6 @@ namespace EleCho.WpfSuite |
|
|
|
_animationRunning = false; |
|
|
|
_animationRunning = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
|
|
|
|
protected override void OnMouseWheel(MouseWheelEventArgs e) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (!ScrollWithWheelDelta) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
base.OnMouseWheel(e); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Debug.WriteLine(e.Delta); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CoreScrollWithWheelDelta(e); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
/// The horizontal offset of scrolling target
|
|
|
|
/// The horizontal offset of scrolling target
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
@ -297,13 +319,13 @@ namespace EleCho.WpfSuite |
|
|
|
/// The key needed set a read-only property
|
|
|
|
/// The key needed set a read-only property
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public static readonly DependencyPropertyKey HorizontalOffsetTargetPropertyKey = |
|
|
|
public static readonly DependencyPropertyKey HorizontalOffsetTargetPropertyKey = |
|
|
|
DependencyProperty.RegisterReadOnly(nameof(HorizontalOffsetTarget), typeof(double), typeof(ScrollViewer), new PropertyMetadata(0.0)); |
|
|
|
DependencyProperty.RegisterReadOnly(nameof(HorizontalOffsetTarget), typeof(double), typeof(SmoothScrollingBehavior), new PropertyMetadata(0.0)); |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
/// The key needed set a read-only property
|
|
|
|
/// The key needed set a read-only property
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public static readonly DependencyPropertyKey VerticalOffsetTargetPropertyKey = |
|
|
|
public static readonly DependencyPropertyKey VerticalOffsetTargetPropertyKey = |
|
|
|
DependencyProperty.RegisterReadOnly(nameof(VerticalOffsetTarget), typeof(double), typeof(ScrollViewer), new PropertyMetadata(0.0)); |
|
|
|
DependencyProperty.RegisterReadOnly(nameof(VerticalOffsetTarget), typeof(double), typeof(SmoothScrollingBehavior), new PropertyMetadata(0.0)); |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
/// The key needed set a read-only property
|
|
|
|
/// The key needed set a read-only property
|
|
|
@ -405,40 +427,40 @@ namespace EleCho.WpfSuite |
|
|
|
/// The DependencyProperty of <see cref="ScrollWithWheelDelta"/> property.
|
|
|
|
/// The DependencyProperty of <see cref="ScrollWithWheelDelta"/> property.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public static readonly DependencyProperty ScrollWithWheelDeltaProperty = |
|
|
|
public static readonly DependencyProperty ScrollWithWheelDeltaProperty = |
|
|
|
DependencyProperty.RegisterAttached(nameof(ScrollWithWheelDelta), typeof(bool), typeof(ScrollViewer), |
|
|
|
DependencyProperty.RegisterAttached(nameof(ScrollWithWheelDelta), typeof(bool), typeof(SmoothScrollingBehavior), |
|
|
|
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits)); |
|
|
|
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits)); |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
/// The DependencyProperty of <see cref="EnableScrollingAnimation"/> property.
|
|
|
|
/// The DependencyProperty of <see cref="EnableScrollingAnimation"/> property.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public static readonly DependencyProperty EnableScrollingAnimationProperty = |
|
|
|
public static readonly DependencyProperty EnableScrollingAnimationProperty = |
|
|
|
DependencyProperty.RegisterAttached(nameof(EnableScrollingAnimation), typeof(bool), typeof(ScrollViewer), |
|
|
|
DependencyProperty.RegisterAttached(nameof(EnableScrollingAnimation), typeof(bool), typeof(SmoothScrollingBehavior), |
|
|
|
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits)); |
|
|
|
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits)); |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
/// The DependencyProperty of <see cref="ScrollingAnimationDuration"/> property.
|
|
|
|
/// The DependencyProperty of <see cref="ScrollingAnimationDuration"/> property.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public static readonly DependencyProperty ScrollingAnimationDurationProperty = |
|
|
|
public static readonly DependencyProperty ScrollingAnimationDurationProperty = |
|
|
|
DependencyProperty.RegisterAttached(nameof(ScrollingAnimationDuration), typeof(Duration), typeof(ScrollViewer), |
|
|
|
DependencyProperty.RegisterAttached(nameof(ScrollingAnimationDuration), typeof(Duration), typeof(SmoothScrollingBehavior), |
|
|
|
new FrameworkPropertyMetadata(new Duration(TimeSpan.FromMilliseconds(250)), FrameworkPropertyMetadataOptions.Inherits), ValidateScrollingAnimationDuration); |
|
|
|
new FrameworkPropertyMetadata(new Duration(TimeSpan.FromMilliseconds(250)), FrameworkPropertyMetadataOptions.Inherits), ValidateScrollingAnimationDuration); |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
/// The DependencyProperty of <see cref="AlwaysHandleMouseWheelScrolling"/> property
|
|
|
|
/// The DependencyProperty of <see cref="AlwaysHandleMouseWheelScrolling"/> property
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public static readonly DependencyProperty AlwaysHandleMouseWheelScrollingProperty = |
|
|
|
public static readonly DependencyProperty AlwaysHandleMouseWheelScrollingProperty = |
|
|
|
DependencyProperty.RegisterAttached(nameof(AlwaysHandleMouseWheelScrolling), typeof(bool), typeof(ScrollViewer), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits)); |
|
|
|
DependencyProperty.RegisterAttached(nameof(AlwaysHandleMouseWheelScrolling), typeof(bool), typeof(SmoothScrollingBehavior), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits)); |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
/// The DependencyProperty of <see cref="MouseScrollDeltaFactor"/> property
|
|
|
|
/// The DependencyProperty of <see cref="MouseScrollDeltaFactor"/> property
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public static readonly DependencyProperty MouseScrollDeltaFactorProperty = |
|
|
|
public static readonly DependencyProperty MouseScrollDeltaFactorProperty = |
|
|
|
DependencyProperty.Register(nameof(MouseScrollDeltaFactor), typeof(double), typeof(ScrollViewer), new PropertyMetadata(1.0)); |
|
|
|
DependencyProperty.Register(nameof(MouseScrollDeltaFactor), typeof(double), typeof(SmoothScrollingBehavior), new PropertyMetadata(1.0)); |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
/// The DependencyProperty of <see cref="TouchpadScrollDeltaFactor"/> property
|
|
|
|
/// The DependencyProperty of <see cref="TouchpadScrollDeltaFactor"/> property
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public static readonly DependencyProperty TouchpadScrollDeltaFactorProperty = |
|
|
|
public static readonly DependencyProperty TouchpadScrollDeltaFactorProperty = |
|
|
|
DependencyProperty.Register(nameof(TouchpadScrollDeltaFactor), typeof(double), typeof(ScrollViewer), new PropertyMetadata(1.0)); |
|
|
|
DependencyProperty.Register(nameof(TouchpadScrollDeltaFactor), typeof(double), typeof(SmoothScrollingBehavior), new PropertyMetadata(1.0)); |
|
|
|
|
|
|
|
|
|
|
|
private static bool ValidateScrollingAnimationDuration(object value) |
|
|
|
private static bool ValidateScrollingAnimationDuration(object value) |
|
|
|
=> value is Duration duration && duration.HasTimeSpan; |
|
|
|
=> value is Duration duration && duration.HasTimeSpan; |