Browse Source

Merge pull request #1676 from sdoroff/scroll-bar-scroll-event

ScrollBar Scroll event
pull/1586/merge
Jeremy Koritzinsky 8 years ago
committed by GitHub
parent
commit
aee5fc54ad
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 37
      src/Avalonia.Controls/Primitives/ScrollBar.cs
  2. 53
      src/Avalonia.Controls/Primitives/ScrollEventType.cs
  3. 59
      tests/Avalonia.Controls.UnitTests/Primitives/ScrollBarTests.cs

37
src/Avalonia.Controls/Primitives/ScrollBar.cs

@ -6,9 +6,21 @@ using System.Reactive;
using System.Reactive.Linq;
using Avalonia.Data;
using Avalonia.Interactivity;
using Avalonia.Input;
namespace Avalonia.Controls.Primitives
{
public class ScrollEventArgs : EventArgs
{
public ScrollEventArgs(ScrollEventType eventType, double newValue)
{
ScrollEventType = eventType;
NewValue = newValue;
}
public double NewValue { get; private set; }
public ScrollEventType ScrollEventType { get; private set; }
}
/// <summary>
/// A scrollbar control.
/// </summary>
@ -44,6 +56,9 @@ namespace Avalonia.Controls.Primitives
{
PseudoClass(OrientationProperty, o => o == Orientation.Vertical, ":vertical");
PseudoClass(OrientationProperty, o => o == Orientation.Horizontal, ":horizontal");
Thumb.DragDeltaEvent.AddClassHandler<ScrollBar>(o => o.OnThumbDragDelta, RoutingStrategies.Bubble);
Thumb.DragCompletedEvent.AddClassHandler<ScrollBar>(o => o.OnThumbDragComplete, RoutingStrategies.Bubble);
}
/// <summary>
@ -88,6 +103,8 @@ namespace Avalonia.Controls.Primitives
set { SetValue(OrientationProperty, value); }
}
public event EventHandler<ScrollEventArgs> Scroll;
/// <summary>
/// Calculates whether the scrollbar should be visible.
/// </summary>
@ -140,6 +157,8 @@ namespace Avalonia.Controls.Primitives
_pageUpButton = e.NameScope.Find<Button>("PART_PageUpButton");
_pageDownButton = e.NameScope.Find<Button>("PART_PageDownButton");
if (_lineUpButton != null)
{
_lineUpButton.Click += LineUpClick;
@ -184,21 +203,39 @@ namespace Avalonia.Controls.Primitives
private void SmallDecrement()
{
Value = Math.Max(Value - SmallChange * ViewportSize, Minimum);
OnScroll(ScrollEventType.SmallDecrement);
}
private void SmallIncrement()
{
Value = Math.Min(Value + SmallChange * ViewportSize, Maximum);
OnScroll(ScrollEventType.SmallIncrement);
}
private void LargeDecrement()
{
Value = Math.Max(Value - LargeChange * ViewportSize, Minimum);
OnScroll(ScrollEventType.LargeDecrement);
}
private void LargeIncrement()
{
Value = Math.Min(Value + LargeChange * ViewportSize, Maximum);
OnScroll(ScrollEventType.LargeIncrement);
}
private void OnThumbDragDelta(VectorEventArgs e)
{
OnScroll(ScrollEventType.ThumbTrack);
}
private void OnThumbDragComplete(VectorEventArgs e)
{
OnScroll(ScrollEventType.EndScroll);
}
protected void OnScroll(ScrollEventType scrollEventType)
{
Scroll?.Invoke(this, new ScrollEventArgs(scrollEventType, Value));
}
}
}

53
src/Avalonia.Controls/Primitives/ScrollEventType.cs

@ -0,0 +1,53 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Controls.Primitives
{
/// <summary>
/// Specifies the type of Avalonia.Controls.Primitives.ScrollBar.Scroll event
/// that occurred.
/// </summary>
public enum ScrollEventType
{
/// <summary>
/// Specifies that the Avalonia.Controls.Primitives.Thumb moved a specified
/// distance, as determined by the value of Avalonia.Controls.Primitives.RangeBase.SmallChange.
/// The Avalonia.Controls.Primitives.Thumb moved to the left for a horizontal
/// Avalonia.Controls.Primitives.ScrollBar or upward for a vertical Avalonia.Controls.Primitives.ScrollBar.
/// </summary>
SmallDecrement = 0,
/// <summary>
/// Specifies that the Avalonia.Controls.Primitives.Thumb moved a specified
/// distance, as determined by the value of Avalonia.Controls.Primitives.RangeBase.SmallChange.
/// The Avalonia.Controls.Primitives.Thumb moved to the right for a horizontal
/// Avalonia.Controls.Primitives.ScrollBar or downward for a vertical Avalonia.Controls.Primitives.ScrollBar.
/// </summary>
SmallIncrement = 1,
/// <summary>
/// Specifies that the Avalonia.Controls.Primitives.Thumb moved a specified
/// distance, as determined by the value of Avalonia.Controls.Primitives.RangeBase.LargeChange.
/// The Avalonia.Controls.Primitives.Thumb moved to the left for a horizontal
/// Avalonia.Controls.Primitives.ScrollBar or upward for a vertical Avalonia.Controls.Primitives.ScrollBar.
/// </summary>
LargeDecrement = 2,
/// <summary>
/// Specifies that the Avalonia.Controls.Primitives.Thumb moved a specified
/// distance, as determined by the value of Avalonia.Controls.Primitives.RangeBase.LargeChange.
/// The Avalonia.Controls.Primitives.Thumb moved to the right for a horizontal
/// Avalonia.Controls.Primitives.ScrollBar or downward for a vertical Avalonia.Controls.Primitives.ScrollBar.
/// </summary>
LargeIncrement = 3,
/// <summary>
/// The Avalonia.Controls.Primitives.Thumb was dragged and caused a Avalonia.UIElement.MouseMove
/// event. A Avalonia.Controls.Primitives.ScrollBar.Scroll event of this Avalonia.Controls.Primitives.ScrollEventType
/// may occur more than one time when the Avalonia.Controls.Primitives.Thumb
/// is dragged in the Avalonia.Controls.Primitives.ScrollBar.
/// </summary>
ThumbTrack = 4,
/// <summary>
/// Specifies that the Avalonia.Controls.Primitives.Thumb was dragged to a
/// new position and is now no longer being dragged by the user.
/// </summary>
EndScroll = 5
}
}

59
tests/Avalonia.Controls.UnitTests/Primitives/ScrollBarTests.cs

@ -5,6 +5,7 @@ using System;
using System.Linq;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Input;
using Avalonia.Media;
using Xunit;
@ -59,6 +60,64 @@ namespace Avalonia.Controls.UnitTests.Primitives
Assert.Equal(50, target.Value);
}
[Fact]
public void Thumb_DragDelta_Event_Should_Raise_Scroll_Event()
{
var target = new ScrollBar
{
Template = new FuncControlTemplate<ScrollBar>(Template),
};
target.ApplyTemplate();
var track = (Track)target.GetTemplateChildren().First(x => x.Name == "track");
var raisedEvent = Assert.Raises<ScrollEventArgs>(
handler => target.Scroll += handler,
handler => target.Scroll -= handler,
() =>
{
var ev = new VectorEventArgs
{
RoutedEvent = Thumb.DragDeltaEvent,
Vector = new Vector(0, 0)
};
track.Thumb.RaiseEvent(ev);
});
Assert.Equal(ScrollEventType.ThumbTrack, raisedEvent.Arguments.ScrollEventType);
}
[Fact]
public void Thumb_DragComplete_Event_Should_Raise_Scroll_Event()
{
var target = new ScrollBar
{
Template = new FuncControlTemplate<ScrollBar>(Template),
};
target.ApplyTemplate();
var track = (Track)target.GetTemplateChildren().First(x => x.Name == "track");
var raisedEvent = Assert.Raises<ScrollEventArgs>(
handler => target.Scroll += handler,
handler => target.Scroll -= handler,
() =>
{
var ev = new VectorEventArgs
{
RoutedEvent = Thumb.DragCompletedEvent,
Vector = new Vector(0, 0)
};
track.Thumb.RaiseEvent(ev);
});
Assert.Equal(ScrollEventType.EndScroll, raisedEvent.Arguments.ScrollEventType);
}
[Fact]
public void ScrollBar_Can_AutoHide()
{

Loading…
Cancel
Save