Arquivo de Fevereiro, 2009

h1

InertiaScrollViewer – ScrollViewer com inercia!

Fevereiro 26, 2009

Com este ScrollViewer temos a capacidade de fazer scroll apenas com o arrastar do rato
Updated

public class InertiaScrollViewer : ScrollViewer
    {
        DispatcherTimer _yourTimer;

        public InertiaScrollViewer()
        {
            _yourTimer = new DispatcherTimer();
            _yourTimer.Interval = new TimeSpan(0, 0, 0, 0, 2);
            _yourTimer.Tick += new EventHandler(yourTimer_Tick);
            _yourTimer.Start();
            this.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden;
            this.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
        }

        #region Overrides

        protected override void OnPreviewMouseDown(System.Windows.Input.MouseButtonEventArgs e)
        {
            base.OnMouseDown(e);
            InertiaScrollViewer.SetIsDragging(this, true);
            InertiaScrollViewer.SetTargetX(this, e.GetPosition(this).X);
            InertiaScrollViewer.SetTargetY(this, e.GetPosition(this).Y);
            double offsetx = this.HorizontalOffset - e.GetPosition(this).X;
            double offsety = this.VerticalOffset - e.GetPosition(this).Y;
            InertiaScrollViewer.SetOffset(this, new Point(offsetx, offsety));
        }

        protected override void OnMouseUp(System.Windows.Input.MouseButtonEventArgs e)
        {
            base.OnMouseUp(e);

            InertiaScrollViewer.SetTargetX(this, (e.GetPosition(this).X));
            InertiaScrollViewer.SetTargetY(this, (e.GetPosition(this).Y));
            InertiaScrollViewer.SetIsDragging(this, false);
        }

        protected override void OnMouseLeave(System.Windows.Input.MouseEventArgs e)
        {
            base.OnMouseLeave(e);
            InertiaScrollViewer.SetIsDragging(this, false);
        }

        protected override void OnPreviewMouseMove(System.Windows.Input.MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if ((InertiaScrollViewer.GetIsDragging(this) == true))
            {
                InertiaScrollViewer.SetTargetX(this, (e.GetPosition(this).X));
                InertiaScrollViewer.SetTargetY(this, (e.GetPosition(this).Y));
            }
        }

        #endregion

        private void yourTimer_Tick(object sender, EventArgs e)
        {
            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
            {
                if (Math.Abs(Math.Round(InertiaScrollViewer.GetVelocityX(this), 3)) != 0.000)
                {
                    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);
                }
            }
        }

        #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.96));

        #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
        #endregion
    }

Para usar basta definir no Template que queremos usar o nosso InertiaScrollViewer

<ItemsControl>
                <ItemsControl.Template>
                    <ControlTemplate>
                        <local:InertiaScrollViewer>
                            <StackPanel IsItemsHost="True"/>
                        </local:InertiaScrollViewer>
                    </ControlTemplate>
                </ItemsControl.Template>
            </ItemsControl>

Em breve vou colocar um Canvas exactamente com o mesmo funcionamento, mas para os UiElements que estão dentro dele…
Até breve,
Miguel Duarte

h1

De volta. E desta vez mais activo

Fevereiro 19, 2009

Bem acho que vou voltar a escrever no meu blog para ajudar e poder ser ajudado sobre algumas questões sobre WPF.
Espero desta vez também ter tempo para abordar um pouco mais a tecnologia, WCF e WF.

Bem… então até breve