Aqui fica o novo codigo do InertiaScrollViewer, tem algumas melhorias principalmente em termos de performance.
public class InertiaScrollViewer : ScrollViewer
{
DispatcherTimer _yourTimer;
public InertiaScrollViewer()
{
_yourTimer = new DispatcherTimer(DispatcherPriority.Normal);
_yourTimer.Interval = TimeSpan.FromMilliseconds(10);
_yourTimer.Tick += new EventHandler(yourTimer_Tick);
this.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden;
this.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
}
#region Overrides
protected override void OnPreviewMouseDown(System.Windows.Input.MouseButtonEventArgs e)
{
Point mouseposition = e.GetPosition(this);
InertiaScrollViewer.SetIsDragging(this, true);
InertiaScrollViewer.SetTargetX(this, mouseposition.X * -1);
InertiaScrollViewer.SetTargetY(this, mouseposition.Y * -1);
double offsetx = this.HorizontalOffset + mouseposition.X;
double offsety = this.VerticalOffset + mouseposition.Y;
InertiaScrollViewer.SetOffset(this, new Point(offsetx, offsety));
_yourTimer.Start();
base.OnMouseDown(e);
}
protected override void OnMouseUp(System.Windows.Input.MouseButtonEventArgs e)
{
Point mouseposition = e.GetPosition(this);
InertiaScrollViewer.SetTargetX(this, (mouseposition.X) * -1);
InertiaScrollViewer.SetTargetY(this, (mouseposition.Y) * -1);
InertiaScrollViewer.SetIsDragging(this, false);
base.OnMouseUp(e);
}
protected override void OnMouseLeave(System.Windows.Input.MouseEventArgs e)
{
InertiaScrollViewer.SetIsDragging(this, false);
base.OnMouseLeave(e);
}
protected override void OnPreviewMouseMove(System.Windows.Input.MouseEventArgs e)
{
if (!CanDrag && (InertiaScrollViewer.GetIsDragging(this) == true))
{
Point mouseposition = e.GetPosition(this);
InertiaScrollViewer.SetTargetX(this, (mouseposition.X) * -1);
InertiaScrollViewer.SetTargetY(this, (mouseposition.Y) * -1);
_yourTimer.Start();
}
base.OnMouseMove(e);
}
#endregion
private void yourTimer_Tick(object sender, EventArgs e)
{
if (!CanDrag)
{
this.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
this.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
if (InertiaScrollViewer.GetIsDragging(this))
{
double oldX = this.HorizontalOffset;
double oldY = this.VerticalOffset;
this.ScrollToVerticalOffset(this.VerticalOffset + (((InertiaScrollViewer.GetTargetY(this) + InertiaScrollViewer.GetOffset(this).Y) - this.VerticalOffset) * .3));
this.ScrollToHorizontalOffset(this.HorizontalOffset + ((InertiaScrollViewer.GetTargetX(this) + InertiaScrollViewer.GetOffset(this).X) - this.HorizontalOffset) * .3);
InertiaScrollViewer.SetVelocityX(this, (this.HorizontalOffset + ((InertiaScrollViewer.GetTargetX(this) + InertiaScrollViewer.GetOffset(this).X) - this.HorizontalOffset) * .3) - oldX);
InertiaScrollViewer.SetVelocityY(this, (this.VerticalOffset + (((InertiaScrollViewer.GetTargetY(this) + InertiaScrollViewer.GetOffset(this).Y) - this.VerticalOffset) * .3)) - oldY);
}
else
{
this.ScrollToHorizontalOffset(this.HorizontalOffset + InertiaScrollViewer.GetVelocityX(this));
this.ScrollToVerticalOffset(this.VerticalOffset + InertiaScrollViewer.GetVelocityY(this));
InertiaScrollViewer.SetVelocityX(this, InertiaScrollViewer.GetVelocityX(this) * VelocityConst);
InertiaScrollViewer.SetVelocityY(this, InertiaScrollViewer.GetVelocityY(this) * VelocityConst);
}
}
if ((Math.Abs(Math.Round(InertiaScrollViewer.GetVelocityX(this), 1)) == 0.0
&& Math.Abs(Math.Round(InertiaScrollViewer.GetVelocityY(this), 1)) == 0.0)
|| (this.ScrollableHeight==this.VerticalOffset && this.ScrollableWidth==this.HorizontalOffset)
|| (0 == this.VerticalOffset && 0 == this.HorizontalOffset))
{
_yourTimer.Stop();
this.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
this.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden;
}
}
#region Properties
#region TargetX
public static double GetTargetX(DependencyObject obj)
{
return (double)obj.GetValue(TargetXProperty);
}
public static void SetTargetX(DependencyObject obj, double value)
{
obj.SetValue(TargetXProperty, value);
}
// Using a DependencyProperty as the backing store for TargetX. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TargetXProperty =
DependencyProperty.Register("TargetX", typeof(double), typeof(InertiaScrollViewer), new UIPropertyMetadata(0.0));
#endregion
#region TargetY
public static double GetTargetY(DependencyObject obj)
{
return (double)obj.GetValue(TargetYProperty);
}
public static void SetTargetY(DependencyObject obj, double value)
{
obj.SetValue(TargetYProperty, value);
}
// Using a DependencyProperty as the backing store for TargetY. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TargetYProperty =
DependencyProperty.Register("TargetY", typeof(double), typeof(InertiaScrollViewer), new UIPropertyMetadata(0.0));
#endregion
#region Offset
public static Point GetOffset(DependencyObject obj)
{
return (Point)obj.GetValue(OffsetProperty);
}
public static void SetOffset(DependencyObject obj, Point value)
{
obj.SetValue(OffsetProperty, value);
}
// Using a DependencyProperty as the backing store for Offset. This enables animation, styling, binding, etc...
public static readonly DependencyProperty OffsetProperty =
DependencyProperty.Register("Offset", typeof(Point), typeof(InertiaScrollViewer), new UIPropertyMetadata(new Point(0, 0)));
#endregion
#region Velocity
public static double GetVelocityX(DependencyObject obj)
{
return (double)obj.GetValue(VelocityXProperty);
}
public static void SetVelocityX(DependencyObject obj, double value)
{
obj.SetValue(VelocityXProperty, value);
}
// Using a DependencyProperty as the backing store for VelocityX. This enables animation, styling, binding, etc...
public static readonly DependencyProperty VelocityXProperty =
DependencyProperty.RegisterAttached("VelocityX", typeof(double), typeof(InertiaScrollViewer), new UIPropertyMetadata(0.0));
public static double GetVelocityY(DependencyObject obj)
{
return (double)obj.GetValue(VelocityYProperty);
}
public static void SetVelocityY(DependencyObject obj, double value)
{
obj.SetValue(VelocityYProperty, value);
}
// Using a DependencyProperty as the backing store for VelocityY. This enables animation, styling, binding, etc...
public static readonly DependencyProperty VelocityYProperty =
DependencyProperty.Register("VelocityY", typeof(double), typeof(InertiaScrollViewer), new UIPropertyMetadata(0.0));
public double VelocityConst
{
get { return (double)GetValue(VelocityConstProperty); }
set { SetValue(VelocityConstProperty, value); }
}
// Using a DependencyProperty as the backing store for VelocityConst. This enables animation, styling, binding, etc...
public static readonly DependencyProperty VelocityConstProperty =
DependencyProperty.Register("VelocityConst", typeof(double), typeof(InertiaScrollViewer), new UIPropertyMetadata(0.97));
#endregion
#region IsDragging
public static bool GetIsDragging(DependencyObject obj)
{
return (bool)obj.GetValue(IsDraggingProperty);
}
public static void SetIsDragging(DependencyObject obj, bool value)
{
obj.SetValue(IsDraggingProperty, value);
}
// Using a DependencyProperty as the backing store for IsDragging. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsDraggingProperty =
DependencyProperty.Register("IsDragging", typeof(bool), typeof(InertiaScrollViewer), new UIPropertyMetadata(false));
#endregion
public bool CanDrag
{
get { return (bool)GetValue(CanDragProperty); }
set { SetValue(CanDragProperty, value); }
}
// Using a DependencyProperty as the backing store for CanDrag. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CanDragProperty =
DependencyProperty.Register("CanDrag", typeof(bool), typeof(InertiaScrollViewer), new UIPropertyMetadata(false));
#endregion
}
Até breve,
Miguel Duarte

