ScrollBar.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Framework / System / Windows / Controls / Primitives / ScrollBar.cs / 1 / ScrollBar.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
//--------------------------------------------------------------------------- 

using System; 
using System.Collections.Specialized; 
using System.ComponentModel;
using System.Diagnostics; 
using System.Globalization;
using System.Windows.Threading;

using System.Windows; 
using System.Windows.Automation;
using System.Windows.Automation.Peers; 
using System.Windows.Controls; 
using System.Windows.Controls.Primitives;
using System.Windows.Data; 

using System.Windows.Media;
using System.Windows.Input;
using System.Windows.Markup; 

using MS.Internal; 
using MS.Internal.Commands; 
using MS.Internal.KnownBoxes;
using MS.Utility; 
using MS.Internal.Utility;
using MS.Win32;
using System.Security;
using System.Security.Permissions; 

namespace System.Windows.Controls.Primitives 
{ 
    /// 
    ///    ScrollBars are the UI widgets that both let a user drive scrolling from the UI 
    ///    and indicate status of scrolled content.
    ///    These are used inside the ScrollViewer.
    ///    Their visibility is determined by the scroller visibility properties on ScrollViewer.
    ///  
    /// 
    [Localizability(LocalizationCategory.NeverLocalize)] 
    [TemplatePart(Name = "PART_Track", Type = typeof(Track))] 
    public class ScrollBar : RangeBase
    { 
        //-------------------------------------------------------------------
        //
        //  Constructors
        // 
        //-------------------------------------------------------------------
 
        #region Constructors 

        ///  
        /// Instantiates a new instance of a ScrollBar.
        /// 
        public ScrollBar() : base()
        { 
        }
 
 
        #endregion Constructors
 
        //--------------------------------------------------------------------
        //
        //  Public Properties
        // 
        //-------------------------------------------------------------------
 
        #region Public Properties 

        ///  
        ///     Event fires when user press mouse's left button on the thumb.
        /// 
        public static readonly RoutedEvent ScrollEvent = EventManager.RegisterRoutedEvent("Scroll", RoutingStrategy.Bubble, typeof(ScrollEventHandler), typeof(ScrollBar));
 
        /// 
        /// Add / Remove Scroll event handler 
        ///  
        [Category("Behavior")]
        public event ScrollEventHandler Scroll { add { AddHandler(ScrollEvent, value); } remove { RemoveHandler(ScrollEvent, value); } } 

        /// 
        /// This property represents the ScrollBar's : Vertical or Horizontal.
        /// On vertical ScrollBars, the thumb moves up and down.  On horizontal bars, the thumb moves left to right. 
        /// 
        public Orientation Orientation 
        { 
            get { return (Orientation) GetValue(OrientationProperty); }
            set { SetValue(OrientationProperty, value); } 
        }

        /// 
        /// ViewportSize is the amount of the scrolled extent currently visible.  For most scrolled content, this value 
        /// will be bound to one of 's ViewportSize properties.
        /// This property is in logical scrolling units. 
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public double ViewportSize 
        {
            get { return (double)GetValue(ViewportSizeProperty); }
            set { SetValue(ViewportSizeProperty, value); }
        } 

        ///  
        /// DependencyProperty for  property. 
        /// 
        public static readonly DependencyProperty OrientationProperty 
            = DependencyProperty.Register("Orientation", typeof(Orientation), typeof(ScrollBar),
                                          new FrameworkPropertyMetadata(Orientation.Vertical),
                                          new ValidateValueCallback(IsValidOrientation));
 

        ///  
        /// DependencyProperty for  property. 
        /// 
        public static readonly DependencyProperty ViewportSizeProperty 
            = DependencyProperty.Register("ViewportSize", typeof(double), typeof(ScrollBar),
                                          new FrameworkPropertyMetadata(0.0d),
                                          new ValidateValueCallback(System.Windows.Shapes.Shape.IsDoubleFiniteNonNegative));
 

        ///  
        /// Gets reference to ScrollBar's Track element. 
        /// 
        public Track Track 
        {
            get
            {
                return _track; 
            }
        } 
 
        #endregion Properties
 
        #region Method Overrides

        /// 
        /// Creates AutomationPeer () 
        /// 
        protected override AutomationPeer OnCreateAutomationPeer() 
        { 
            return new ScrollBarAutomationPeer(this);
        } 

        /// 
        /// ScrollBar supports 'Move-To-Point' by pre-processes Shift+MouseLeftButton Click.
        ///  
        /// 
        protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) 
        { 
            _thumbOffset = new Vector();
            if ((Track != null) && 
                (Track.IsMouseOver) &&
                ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift))
            {
                // Move Thumb to the Mouse location 
                Point pt = e.MouseDevice.GetPosition((IInputElement)Track);
                double newValue = Track.ValueFromPoint(pt); 
                if (System.Windows.Shapes.Shape.IsDoubleFinite(newValue)) 
                {
                    ChangeValue(newValue, false /* defer */); 
                }

                if (Track.Thumb != null && Track.Thumb.IsMouseOver)
                { 
                    Point thumbPoint = e.MouseDevice.GetPosition((IInputElement)Track.Thumb);
                    _thumbOffset = thumbPoint - new Point(Track.Thumb.ActualWidth * 0.5, Track.Thumb.ActualHeight * 0.5); 
                } 
                else
                { 
                    e.Handled = true;
                }

 

            } 
 
            base.OnPreviewMouseLeftButtonDown(e);
        } 

        /// 
        /// ScrollBar need to remember the point which ContextMenu is invoke in order to perform 'Scroll Here' command correctly.
        ///  
        /// 
        protected override void OnPreviewMouseRightButtonUp(MouseButtonEventArgs e) 
        { 
            if (Track != null)
            { 
                // Remember the mouse point (relative to Track's co-ordinate).
                _latestRightButtonClickPoint = e.MouseDevice.GetPosition((IInputElement)Track);
            }
            else 
            {
                // Clear the mouse point 
                _latestRightButtonClickPoint = new Point(-1,-1); 
            }
 
            base.OnPreviewMouseRightButtonUp(e);
        }

 
        /// 
        ///     Fetches the value of the IsEnabled property 
        ///  
        /// 
        ///     The reason this property is overridden is so that ScrollBar 
        ///     could infuse the value for EnoughContentToScroll into it.
        /// 
        protected override bool IsEnabledCore
        { 
            get
            { 
                return base.IsEnabledCore && _canScroll; 
            }
        } 

        /// 
        /// ScrollBar locates the Track element when its visual tree is created
        ///  
        public override void OnApplyTemplate()
        { 
            base.OnApplyTemplate(); 
            _track = GetTemplateChild(TrackName) as Track;
        } 

        #endregion

        ///  
        /// Scroll content by one line to the top.
        ///  
        public static readonly RoutedCommand LineUpCommand = new RoutedCommand("LineUp", typeof(ScrollBar)); 
        /// 
        /// Scroll content by one line to the bottom. 
        /// 
        public static readonly RoutedCommand LineDownCommand = new RoutedCommand("LineDown", typeof(ScrollBar));
        /// 
        /// Scroll content by one line to the left. 
        /// 
        public static readonly RoutedCommand LineLeftCommand = new RoutedCommand("LineLeft", typeof(ScrollBar)); 
        ///  
        /// Scroll content by one line to the right.
        ///  
        public static readonly RoutedCommand LineRightCommand = new RoutedCommand("LineRight", typeof(ScrollBar));
        /// 
        /// Scroll content by one page to the top.
        ///  
        public static readonly RoutedCommand PageUpCommand = new RoutedCommand("PageUp", typeof(ScrollBar));
        ///  
        /// Scroll content by one page to the bottom. 
        /// 
        public static readonly RoutedCommand PageDownCommand = new RoutedCommand("PageDown", typeof(ScrollBar)); 
        /// 
        /// Scroll content by one page to the left.
        /// 
        public static readonly RoutedCommand PageLeftCommand = new RoutedCommand("PageLeft", typeof(ScrollBar)); 
        /// 
        /// Scroll content by one page to the right. 
        ///  
        public static readonly RoutedCommand PageRightCommand = new RoutedCommand("PageRight", typeof(ScrollBar));
        ///  
        /// Horizontally scroll to the beginning of the content.
        /// 
        public static readonly RoutedCommand ScrollToEndCommand = new RoutedCommand("ScrollToEnd", typeof(ScrollBar));
        ///  
        /// Horizontally scroll to the end of the content.
        ///  
        public static readonly RoutedCommand ScrollToHomeCommand = new RoutedCommand("ScrollToHome", typeof(ScrollBar)); 
        /// 
        /// Horizontally scroll to the beginning of the content. 
        /// 
        public static readonly RoutedCommand ScrollToRightEndCommand = new RoutedCommand("ScrollToRightEnd", typeof(ScrollBar));
        /// 
        /// Horizontally scroll to the end of the content. 
        /// 
        public static readonly RoutedCommand ScrollToLeftEndCommand = new RoutedCommand("ScrollToLeftEnd", typeof(ScrollBar)); 
        ///  
        /// Vertically scroll to the beginning of the content.
        ///  
        public static readonly RoutedCommand ScrollToTopCommand = new RoutedCommand("ScrollToTop", typeof(ScrollBar));
        /// 
        /// Vertically scroll to the end of the content.
        ///  
        public static readonly RoutedCommand ScrollToBottomCommand = new RoutedCommand("ScrollToBottom", typeof(ScrollBar));
        ///  
        /// Scrolls horizontally to the double value provided in . 
        /// 
        public static readonly RoutedCommand ScrollToHorizontalOffsetCommand = new RoutedCommand("ScrollToHorizontalOffset", typeof(ScrollBar)); 
        /// 
        /// Scrolls vertically to the double value provided in .
        /// 
        public static readonly RoutedCommand ScrollToVerticalOffsetCommand = new RoutedCommand("ScrollToVerticalOffset", typeof(ScrollBar)); 
        /// 
        /// Scrolls horizontally by dragging to the double value provided in . 
        ///  
        public static readonly RoutedCommand DeferScrollToHorizontalOffsetCommand = new RoutedCommand("DeferScrollToToHorizontalOffset", typeof(ScrollBar));
        ///  
        /// Scrolls vertically by dragging to the double value provided in .
        /// 
        public static readonly RoutedCommand DeferScrollToVerticalOffsetCommand = new RoutedCommand("DeferScrollToVerticalOffset", typeof(ScrollBar));
 
        /// 
        /// Scroll to the point where user invoke ScrollBar ContextMenu.  This command is always handled by ScrollBar. 
        ///  
        public static readonly RoutedCommand ScrollHereCommand = new RoutedCommand("ScrollHere", typeof(ScrollBar));
 

        //--------------------------------------------------------------------
        //
        //  Private Methods (and Event Handlers) 
        //
        //-------------------------------------------------------------------- 
 
        #region Private Methods
 
        private static void OnThumbDragStarted(object sender, DragStartedEventArgs e)
        {
            ScrollBar scrollBar = sender as ScrollBar;
            if (scrollBar == null) { return; } 

            scrollBar._hasScrolled = false; 
            scrollBar._previousValue = scrollBar.Value; 
        }
 
        // Event handler to listen to thumb events.
        private static void OnThumbDragDelta(object sender, DragDeltaEventArgs e)
        {
            ScrollBar scrollBar = sender as ScrollBar; 
            if (scrollBar == null) { return; }
 
            scrollBar.UpdateValue(e.HorizontalChange + scrollBar._thumbOffset.X, e.VerticalChange + scrollBar._thumbOffset.Y); 
        }
 
        // Update ScrollBar Value based on the Thumb drag delta.
        // Deal with pixel -> logical scrolling unit conversion, and restrict the value to within [Minimum, Maximum].
        private void UpdateValue(double horizontalDragDelta, double verticalDragDelta)
        { 
            if (Track != null)
            { 
                double valueDelta = Track.ValueFromDistance(horizontalDragDelta, verticalDragDelta); 
                if (    System.Windows.Shapes.Shape.IsDoubleFinite(valueDelta)
                    &&  !DoubleUtil.IsZero(valueDelta)) 
                {
                    double currentValue = Value;
                    double newValue = currentValue + valueDelta;
 
                    double perpendicularDragDelta;
 
                    // Compare distances from thumb for horizontal and vertical orientations 
                    if (Orientation == Orientation.Horizontal)
                    { 
                        perpendicularDragDelta = Math.Abs(verticalDragDelta);
                    }
                    else //Orientation == Orientation.Vertical
                    { 
                        perpendicularDragDelta = Math.Abs(horizontalDragDelta);
                    } 
 
                    if (DoubleUtil.GreaterThan(perpendicularDragDelta, MaxPerpendicularDelta))
                    { 
                        newValue = _previousValue;
                    }

                    if (!DoubleUtil.AreClose(currentValue, newValue)) 
                    {
                        _hasScrolled = true; 
                        ChangeValue(newValue, true /* defer */); 
                        RaiseScrollEvent(ScrollEventType.ThumbTrack);
                    } 
                }
            }
        }
 
        /// 
        /// Listen to Thumb DragCompleted event. 
        ///  
        /// 
        ///  
        private static void OnThumbDragCompleted(object sender, DragCompletedEventArgs e)
        {
            ((ScrollBar)sender).OnThumbDragCompleted(e);
        } 

        ///  
        /// Called when user dragging the Thumb. 
        /// This function can be override to customize the way Slider handles Thumb movement.
        ///  
        /// 
        private void OnThumbDragCompleted(DragCompletedEventArgs e)
        {
            if (_hasScrolled) 
            {
                FinishDrag(); 
                RaiseScrollEvent(ScrollEventType.EndScroll); 
            }
        } 

        private IInputElement CommandTarget
        {
            get 
            {
                IInputElement target = TemplatedParent as IInputElement; 
                if (target == null) 
                {
                    target = this; 
                }

                return target;
            } 
        }
 
        private void FinishDrag() 
        {
            double value = Value; 
            IInputElement target = CommandTarget;
            RoutedCommand command = (Orientation == Orientation.Horizontal) ? DeferScrollToHorizontalOffsetCommand : DeferScrollToVerticalOffsetCommand;

            if (command.CanExecute(value, target)) 
            {
                // If we were reporting drag commands, we need to give a final scroll command 
                ChangeValue(value, false /* defer */); 
            }
        } 


        private void ChangeValue(double newValue, bool defer)
        { 
            newValue = Math.Min(Math.Max(newValue, Minimum), Maximum);
            if (IsStandalone) { Value = newValue; } 
            else 
            {
                IInputElement target = CommandTarget; 
                RoutedCommand command = null;
                bool horizontal = (Orientation == Orientation.Horizontal);

                // Fire the deferred (drag) version of the command 
                if (defer)
                { 
                    command = horizontal ? DeferScrollToHorizontalOffsetCommand : DeferScrollToVerticalOffsetCommand; 
                    if (command.CanExecute(newValue, target))
                    { 
                        // The defer version of the command is enabled, fire this command and not the scroll version
                        command.Execute(newValue, target);
                    }
                    else 
                    {
                        // The defer version of the command is not enabled, reset and try the scroll version 
                        command = null; 
                    }
                } 

                if (command == null)
                {
                    // Either we're not dragging or the drag command is not enabled, try the scroll version 
                    command = horizontal ? ScrollToHorizontalOffsetCommand : ScrollToVerticalOffsetCommand;
                    if (command.CanExecute(newValue, target)) 
                    { 
                        command.Execute(newValue, target);
                    } 
                }
            }
        }
 
        /// 
        /// Scroll to the position where ContextMenu was invoked. 
        ///  
        internal void ScrollToLastMousePoint()
        { 
            Point pt = new Point(-1,-1);
            if ((Track != null) && (_latestRightButtonClickPoint != pt))
            {
                double newValue = Track.ValueFromPoint(_latestRightButtonClickPoint); 
                if (System.Windows.Shapes.Shape.IsDoubleFinite(newValue))
                { 
                    ChangeValue(newValue, false /* defer */); 
                    _latestRightButtonClickPoint = pt;
                    RaiseScrollEvent(ScrollEventType.ThumbPosition); 
                }
            }
        }
 
        internal void RaiseScrollEvent(ScrollEventType scrollEventType)
        { 
            ScrollEventArgs newEvent = new ScrollEventArgs(scrollEventType, Value); 
            newEvent.Source=this;
            RaiseEvent(newEvent); 
        }

        private static void OnScrollCommand(object target, ExecutedRoutedEventArgs args)
        { 
            ScrollBar scrollBar = ((ScrollBar)target);
            if (args.Command == ScrollBar.ScrollHereCommand) 
            { 
                scrollBar.ScrollToLastMousePoint();
            } 

            if (scrollBar.IsStandalone)
            {
                if (scrollBar.Orientation == Orientation.Vertical) 
                {
                    if (args.Command == ScrollBar.LineUpCommand) 
                    { 
                        scrollBar.LineUp();
                    } 
                    else if (args.Command == ScrollBar.LineDownCommand)
                    {
                        scrollBar.LineDown();
                    } 
                    else if (args.Command == ScrollBar.PageUpCommand)
                    { 
                        scrollBar.PageUp(); 
                    }
                    else if (args.Command == ScrollBar.PageDownCommand) 
                    {
                        scrollBar.PageDown();
                    }
                    else if (args.Command == ScrollBar.ScrollToTopCommand) 
                    {
                        scrollBar.ScrollToTop(); 
                    } 
                    else if (args.Command == ScrollBar.ScrollToBottomCommand)
                    { 
                        scrollBar.ScrollToBottom();
                    }
                }
                else //Horizontal 
                {
                    if (args.Command == ScrollBar.LineLeftCommand) 
                    { 
                        scrollBar.LineLeft();
                    } 
                    else if (args.Command == ScrollBar.LineRightCommand)
                    {
                        scrollBar.LineRight();
                    } 
                    else if (args.Command == ScrollBar.PageLeftCommand)
                    { 
                        scrollBar.PageLeft(); 
                    }
                    else if (args.Command == ScrollBar.PageRightCommand) 
                    {
                        scrollBar.PageRight();
                    }
                    else if (args.Command == ScrollBar.ScrollToLeftEndCommand) 
                    {
                        scrollBar.ScrollToLeftEnd(); 
                    } 
                    else if (args.Command == ScrollBar.ScrollToRightEndCommand)
                    { 
                        scrollBar.ScrollToRightEnd();
                    }
                }
            } 
        }
 
        private void SmallDecrement() 
        {
            double newValue = Math.Max(Value - SmallChange, Minimum); 
            if (Value != newValue)
            {
                Value = newValue;
                RaiseScrollEvent(ScrollEventType.SmallDecrement); 
            }
        } 
        private void SmallIncrement() 
        {
            double newValue = Math.Min(Value + SmallChange, Maximum); 
            if (Value != newValue)
            {
                Value = newValue;
                RaiseScrollEvent(ScrollEventType.SmallIncrement); 
            }
        } 
        private void LargeDecrement() 
        {
            double newValue = Math.Max(Value - LargeChange, Minimum); 
            if (Value != newValue)
            {
                Value = newValue;
                RaiseScrollEvent(ScrollEventType.LargeDecrement); 
            }
        } 
        private void LargeIncrement() 
        {
            double newValue = Math.Min(Value + LargeChange, Maximum); 
            if (Value != newValue)
            {
                Value = newValue;
                RaiseScrollEvent(ScrollEventType.LargeIncrement); 
            }
        } 
        private void ToMinimum() 
        {
            if (Value != Minimum) 
            {
                Value = Minimum;
                RaiseScrollEvent(ScrollEventType.First);
            } 
        }
        private void ToMaximum() 
        { 
            if (Value != Maximum)
            { 
                Value = Maximum;
                RaiseScrollEvent(ScrollEventType.Last);
            }
        } 
        private void LineUp()
        { 
            SmallDecrement(); 
        }
        private void LineDown() 
        {
            SmallIncrement();
        }
        private void PageUp() 
        {
            LargeDecrement(); 
        } 
        private void PageDown()
        { 
            LargeIncrement();
        }
        private void ScrollToTop()
        { 
            ToMinimum();
        } 
        private void ScrollToBottom() 
        {
            ToMaximum(); 
        }
        private void LineLeft()
        {
            SmallDecrement(); 
        }
        private void LineRight() 
        { 
            SmallIncrement();
        } 
        private void PageLeft()
        {
            LargeDecrement();
        } 
        private void PageRight()
        { 
            LargeIncrement(); 
        }
        private void ScrollToLeftEnd() 
        {
            ToMinimum();
        }
        private void ScrollToRightEnd() 
        {
            ToMaximum(); 
        } 

        private static void OnQueryScrollHereCommand(object target, CanExecuteRoutedEventArgs args) 
        {
            args.CanExecute = (args.Command == ScrollBar.ScrollHereCommand);
        }
 
        private static void OnQueryScrollCommand(object target, CanExecuteRoutedEventArgs args)
        { 
            args.CanExecute = ((ScrollBar)target).IsStandalone; 
        }
 
        #endregion

        //-------------------------------------------------------------------
        // 
        //  Private Members
        // 
        //-------------------------------------------------------------------- 

        #region Private Members 

        #endregion

        //------------------------------------------------------------------- 
        //
        //  Static Constructor & Delegates 
        // 
        //-------------------------------------------------------------------
 
        #region Static Constructor & Delegates

        static ScrollBar()
        { 
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ScrollBar), new FrameworkPropertyMetadata(typeof(ScrollBar)));
            _dType = DependencyObjectType.FromSystemTypeInternal(typeof(ScrollBar)); 
 
            var onScrollCommand = new ExecutedRoutedEventHandler(OnScrollCommand);
            var onQueryScrollCommand = new CanExecuteRoutedEventHandler(OnQueryScrollCommand); 

            FocusableProperty.OverrideMetadata(typeof(ScrollBar), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox));

            // Register Event Handler for the Thumb 
            EventManager.RegisterClassHandler(typeof(ScrollBar), Thumb.DragStartedEvent, new DragStartedEventHandler(OnThumbDragStarted));
            EventManager.RegisterClassHandler(typeof(ScrollBar), Thumb.DragDeltaEvent, new DragDeltaEventHandler(OnThumbDragDelta)); 
            EventManager.RegisterClassHandler(typeof(ScrollBar), Thumb.DragCompletedEvent, new DragCompletedEventHandler(OnThumbDragCompleted)); 

            // ScrollBar has common handler for ScrollHere command. 
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.ScrollHereCommand, onScrollCommand, new CanExecuteRoutedEventHandler(OnQueryScrollHereCommand));
            // Vertical Commands
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.LineUpCommand, onScrollCommand, onQueryScrollCommand, Key.Up);
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.LineDownCommand, onScrollCommand, onQueryScrollCommand, Key.Down); 
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.PageUpCommand, onScrollCommand, onQueryScrollCommand, Key.PageUp);
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.PageDownCommand, onScrollCommand, onQueryScrollCommand, Key.PageDown); 
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.ScrollToTopCommand, onScrollCommand, onQueryScrollCommand, new KeyGesture(Key.Home, ModifierKeys.Control)); 
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.ScrollToBottomCommand, onScrollCommand, onQueryScrollCommand, new KeyGesture(Key.End, ModifierKeys.Control));
            // Horizontal Commands 
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.LineLeftCommand, onScrollCommand, onQueryScrollCommand, Key.Left);
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.LineRightCommand, onScrollCommand, onQueryScrollCommand, Key.Right);
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.PageLeftCommand, onScrollCommand, onQueryScrollCommand);
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.PageRightCommand, onScrollCommand, onQueryScrollCommand); 
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.ScrollToLeftEndCommand, onScrollCommand, onQueryScrollCommand, Key.Home);
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.ScrollToRightEndCommand, onScrollCommand, onQueryScrollCommand, Key.End); 
 
            MaximumProperty.OverrideMetadata(typeof(ScrollBar), new FrameworkPropertyMetadata(new PropertyChangedCallback(ViewChanged)));
            MinimumProperty.OverrideMetadata(typeof(ScrollBar), new FrameworkPropertyMetadata(new PropertyChangedCallback(ViewChanged))); 

            ContextMenuProperty.OverrideMetadata(typeof(ScrollBar), new FrameworkPropertyMetadata(null, new CoerceValueCallback(CoerceContextMenu)));
        }
 
        private static void ViewChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            ScrollBar scrollBar = (ScrollBar)d; 

            bool canScrollNew = scrollBar.Maximum > scrollBar.Minimum; 

            if (canScrollNew != scrollBar._canScroll)
            {
                scrollBar._canScroll = canScrollNew; 
                scrollBar.CoerceValue(IsEnabledProperty);
            } 
        } 

        // Consider adding a verify for ViewportSize to check > 0.0 

        internal static bool IsValidOrientation(object o)
        {
            Orientation value = (Orientation)o; 
            return value == Orientation.Horizontal
                || value == Orientation.Vertical; 
        } 

        // Is the scrollbar outside of a scrollviewer? 
        internal bool IsStandalone
        {
            get { return _isStandalone; }
            set { _isStandalone = value; } 
        }
 
        // Maximum distance you can drag from thumb before it snaps back 
        private const double MaxPerpendicularDelta = 150;
        private const string TrackName = "PART_Track"; 

        private Track _track;

        private Point _latestRightButtonClickPoint = new Point(-1,-1); 

        private bool _canScroll = true;  // Maximum > Minimum by default 
        private bool _hasScrolled;  // Has the thumb been dragged 
        private bool _isStandalone = true;
        private bool _openingContextMenu; 
        private double _previousValue;
        private Vector _thumbOffset;

 

        #endregion 
 

        #region DTypeThemeStyleKey 

        // Returns the DependencyObjectType for the registered ThemeStyleKey's default
        // value. Controls will override this method to return approriate types.
        internal override DependencyObjectType DTypeThemeStyleKey 
        {
            get { return _dType; } 
        } 

        private static DependencyObjectType _dType; 

        #endregion DTypeThemeStyleKey

        #region ContextMenu 

        private static object CoerceContextMenu(DependencyObject o, object value) 
        { 
            bool hasModifiers;
            ScrollBar sb = (ScrollBar)o; 
            if (sb._openingContextMenu &&
                sb.GetValueSource(ContextMenuProperty, null, out hasModifiers) == BaseValueSourceInternal.Default && !hasModifiers)
            {
                // Use a default menu 
                if (sb.Orientation == Orientation.Vertical)
                { 
                    return VerticalContextMenu; 
                }
                else if (sb.FlowDirection == FlowDirection.LeftToRight) 
                {
                    return HorizontalContextMenuLTR;
                }
                else 
                {
                    return HorizontalContextMenuRTL; 
                } 
            }
            return value; 
        }

        /// 
        ///     Called when ContextMenuOpening is raised on this element. 
        /// 
        /// Event arguments 
        protected override void OnContextMenuOpening(ContextMenuEventArgs e) 
        {
            base.OnContextMenuOpening(e); 

            if (!e.Handled)
            {
                _openingContextMenu = true; 
                CoerceValue(ContextMenuProperty);
            } 
        } 

        ///  
        ///     Called when ContextMenuOpening is raised on this element.
        /// 
        /// Event arguments
        protected override void OnContextMenuClosing(ContextMenuEventArgs e) 
        {
            base.OnContextMenuClosing(e); 
 
            _openingContextMenu = false;
            CoerceValue(ContextMenuProperty); 
        }

        private static ContextMenu VerticalContextMenu
        { 
            get
            { 
                ContextMenu verticalContextMenu = new ContextMenu(); 
                verticalContextMenu.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_ScrollHere, "ScrollHere", ScrollBar.ScrollHereCommand));
                verticalContextMenu.Items.Add(new Separator()); 
                verticalContextMenu.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_Top, "Top", ScrollBar.ScrollToTopCommand));
                verticalContextMenu.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_Bottom, "Bottom", ScrollBar.ScrollToBottomCommand));
                verticalContextMenu.Items.Add(new Separator());
                verticalContextMenu.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_PageUp, "PageUp", ScrollBar.PageUpCommand)); 
                verticalContextMenu.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_PageDown, "PageDown", ScrollBar.PageDownCommand));
                verticalContextMenu.Items.Add(new Separator()); 
                verticalContextMenu.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_ScrollUp, "ScrollUp", ScrollBar.LineUpCommand)); 
                verticalContextMenu.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_ScrollDown, "ScrollDown", ScrollBar.LineDownCommand));
                return verticalContextMenu; 
            }
        }

        // LeftToRight menu 
        private static ContextMenu HorizontalContextMenuLTR
        { 
            get 
            {
                ContextMenu horizontalContextMenuLeftToRight = new ContextMenu(); 
                horizontalContextMenuLeftToRight.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_ScrollHere, "ScrollHere", ScrollBar.ScrollHereCommand));
                horizontalContextMenuLeftToRight.Items.Add(new Separator());
                horizontalContextMenuLeftToRight.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_LeftEdge, "LeftEdge", ScrollBar.ScrollToLeftEndCommand));
                horizontalContextMenuLeftToRight.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_RightEdge, "RightEdge", ScrollBar.ScrollToRightEndCommand)); 
                horizontalContextMenuLeftToRight.Items.Add(new Separator());
                horizontalContextMenuLeftToRight.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_PageLeft, "PageLeft", ScrollBar.PageLeftCommand)); 
                horizontalContextMenuLeftToRight.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_PageRight, "PageRight", ScrollBar.PageRightCommand)); 
                horizontalContextMenuLeftToRight.Items.Add(new Separator());
                horizontalContextMenuLeftToRight.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_ScrollLeft, "ScrollLeft", ScrollBar.LineLeftCommand)); 
                horizontalContextMenuLeftToRight.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_ScrollRight, "ScrollRight", ScrollBar.LineRightCommand));
                return horizontalContextMenuLeftToRight;
            }
        } 

        // RightToLeft menu 
        private static ContextMenu HorizontalContextMenuRTL 
        {
            get 
            {
                ContextMenu horizontalContextMenuRightToLeft = new ContextMenu();
                horizontalContextMenuRightToLeft.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_ScrollHere, "ScrollHere", ScrollBar.ScrollHereCommand));
                horizontalContextMenuRightToLeft.Items.Add(new Separator()); 
                horizontalContextMenuRightToLeft.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_LeftEdge, "LeftEdge", ScrollBar.ScrollToRightEndCommand));
                horizontalContextMenuRightToLeft.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_RightEdge, "RightEdge", ScrollBar.ScrollToLeftEndCommand)); 
                horizontalContextMenuRightToLeft.Items.Add(new Separator()); 
                horizontalContextMenuRightToLeft.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_PageLeft, "PageLeft", ScrollBar.PageRightCommand));
                horizontalContextMenuRightToLeft.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_PageRight, "PageRight", ScrollBar.PageLeftCommand)); 
                horizontalContextMenuRightToLeft.Items.Add(new Separator());
                horizontalContextMenuRightToLeft.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_ScrollLeft, "ScrollLeft", ScrollBar.LineRightCommand));
                horizontalContextMenuRightToLeft.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_ScrollRight, "ScrollRight", ScrollBar.LineLeftCommand));
                return horizontalContextMenuRightToLeft; 
            }
        } 
 
        private static MenuItem CreateMenuItem(string name, string automationId, RoutedCommand command)
        { 
            MenuItem menuItem = new MenuItem();
            menuItem.Header = SR.Get(name);
            menuItem.Command = command;
            AutomationProperties.SetAutomationId(menuItem, automationId); 

            Binding binding = new Binding(); 
            binding.Path = new PropertyPath(ContextMenu.PlacementTargetProperty); 
            binding.Mode = BindingMode.OneWay;
            binding.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(ContextMenu), 1); 
            menuItem.SetBinding(MenuItem.CommandTargetProperty, binding);

            return menuItem;
        } 

        // 
        //  This property 
        //  1. Finds the correct initial size for the _effectiveValues store on the current DependencyObject
        //  2. This is a performance optimization 
        //
        internal override int EffectiveValuesInitialSize
        {
            get { return 42; } 
        }
 
        #endregion ContextMenu 
    }
 
    /// 
    /// Type of scrolling that causes ScrollEvent.
    /// 
    public enum ScrollEventType 
    {
        ///  
        /// Thumb has stopped moving. 
        /// 
        EndScroll, 
        /// 
        /// Thumb was moved to the Minimum position.
        /// 
        First, 
        /// 
        /// Thumb was moved a large distance. The user clicked the scroll bar to the left(horizontal) or above(vertical) the scroll box. 
        ///  
        LargeDecrement,
        ///  
        /// Thumb was moved a large distance. The user clicked the scroll bar to the right(horizontal) or below(vertical) the scroll box.
        /// 
        LargeIncrement,
        ///  
        /// Thumb was moved to the Maximum position
        ///  
        Last, 
        /// 
        /// Thumb was moved a small distance. The user clicked the left(horizontal) or top(vertical) scroll arrow. 
        /// 
        SmallDecrement,
        /// 
        /// Thumb was moved a small distance. The user clicked the right(horizontal) or bottom(vertical) scroll arrow. 
        /// 
        SmallIncrement, 
        ///  
        /// Thumb was moved.
        ///  
        ThumbPosition,
        /// 
        /// Thumb is currently being moved.
        ///  
        ThumbTrack
    } 
 
}
 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
//--------------------------------------------------------------------------- 

using System; 
using System.Collections.Specialized; 
using System.ComponentModel;
using System.Diagnostics; 
using System.Globalization;
using System.Windows.Threading;

using System.Windows; 
using System.Windows.Automation;
using System.Windows.Automation.Peers; 
using System.Windows.Controls; 
using System.Windows.Controls.Primitives;
using System.Windows.Data; 

using System.Windows.Media;
using System.Windows.Input;
using System.Windows.Markup; 

using MS.Internal; 
using MS.Internal.Commands; 
using MS.Internal.KnownBoxes;
using MS.Utility; 
using MS.Internal.Utility;
using MS.Win32;
using System.Security;
using System.Security.Permissions; 

namespace System.Windows.Controls.Primitives 
{ 
    /// 
    ///    ScrollBars are the UI widgets that both let a user drive scrolling from the UI 
    ///    and indicate status of scrolled content.
    ///    These are used inside the ScrollViewer.
    ///    Their visibility is determined by the scroller visibility properties on ScrollViewer.
    ///  
    /// 
    [Localizability(LocalizationCategory.NeverLocalize)] 
    [TemplatePart(Name = "PART_Track", Type = typeof(Track))] 
    public class ScrollBar : RangeBase
    { 
        //-------------------------------------------------------------------
        //
        //  Constructors
        // 
        //-------------------------------------------------------------------
 
        #region Constructors 

        ///  
        /// Instantiates a new instance of a ScrollBar.
        /// 
        public ScrollBar() : base()
        { 
        }
 
 
        #endregion Constructors
 
        //--------------------------------------------------------------------
        //
        //  Public Properties
        // 
        //-------------------------------------------------------------------
 
        #region Public Properties 

        ///  
        ///     Event fires when user press mouse's left button on the thumb.
        /// 
        public static readonly RoutedEvent ScrollEvent = EventManager.RegisterRoutedEvent("Scroll", RoutingStrategy.Bubble, typeof(ScrollEventHandler), typeof(ScrollBar));
 
        /// 
        /// Add / Remove Scroll event handler 
        ///  
        [Category("Behavior")]
        public event ScrollEventHandler Scroll { add { AddHandler(ScrollEvent, value); } remove { RemoveHandler(ScrollEvent, value); } } 

        /// 
        /// This property represents the ScrollBar's : Vertical or Horizontal.
        /// On vertical ScrollBars, the thumb moves up and down.  On horizontal bars, the thumb moves left to right. 
        /// 
        public Orientation Orientation 
        { 
            get { return (Orientation) GetValue(OrientationProperty); }
            set { SetValue(OrientationProperty, value); } 
        }

        /// 
        /// ViewportSize is the amount of the scrolled extent currently visible.  For most scrolled content, this value 
        /// will be bound to one of 's ViewportSize properties.
        /// This property is in logical scrolling units. 
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public double ViewportSize 
        {
            get { return (double)GetValue(ViewportSizeProperty); }
            set { SetValue(ViewportSizeProperty, value); }
        } 

        ///  
        /// DependencyProperty for  property. 
        /// 
        public static readonly DependencyProperty OrientationProperty 
            = DependencyProperty.Register("Orientation", typeof(Orientation), typeof(ScrollBar),
                                          new FrameworkPropertyMetadata(Orientation.Vertical),
                                          new ValidateValueCallback(IsValidOrientation));
 

        ///  
        /// DependencyProperty for  property. 
        /// 
        public static readonly DependencyProperty ViewportSizeProperty 
            = DependencyProperty.Register("ViewportSize", typeof(double), typeof(ScrollBar),
                                          new FrameworkPropertyMetadata(0.0d),
                                          new ValidateValueCallback(System.Windows.Shapes.Shape.IsDoubleFiniteNonNegative));
 

        ///  
        /// Gets reference to ScrollBar's Track element. 
        /// 
        public Track Track 
        {
            get
            {
                return _track; 
            }
        } 
 
        #endregion Properties
 
        #region Method Overrides

        /// 
        /// Creates AutomationPeer () 
        /// 
        protected override AutomationPeer OnCreateAutomationPeer() 
        { 
            return new ScrollBarAutomationPeer(this);
        } 

        /// 
        /// ScrollBar supports 'Move-To-Point' by pre-processes Shift+MouseLeftButton Click.
        ///  
        /// 
        protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) 
        { 
            _thumbOffset = new Vector();
            if ((Track != null) && 
                (Track.IsMouseOver) &&
                ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift))
            {
                // Move Thumb to the Mouse location 
                Point pt = e.MouseDevice.GetPosition((IInputElement)Track);
                double newValue = Track.ValueFromPoint(pt); 
                if (System.Windows.Shapes.Shape.IsDoubleFinite(newValue)) 
                {
                    ChangeValue(newValue, false /* defer */); 
                }

                if (Track.Thumb != null && Track.Thumb.IsMouseOver)
                { 
                    Point thumbPoint = e.MouseDevice.GetPosition((IInputElement)Track.Thumb);
                    _thumbOffset = thumbPoint - new Point(Track.Thumb.ActualWidth * 0.5, Track.Thumb.ActualHeight * 0.5); 
                } 
                else
                { 
                    e.Handled = true;
                }

 

            } 
 
            base.OnPreviewMouseLeftButtonDown(e);
        } 

        /// 
        /// ScrollBar need to remember the point which ContextMenu is invoke in order to perform 'Scroll Here' command correctly.
        ///  
        /// 
        protected override void OnPreviewMouseRightButtonUp(MouseButtonEventArgs e) 
        { 
            if (Track != null)
            { 
                // Remember the mouse point (relative to Track's co-ordinate).
                _latestRightButtonClickPoint = e.MouseDevice.GetPosition((IInputElement)Track);
            }
            else 
            {
                // Clear the mouse point 
                _latestRightButtonClickPoint = new Point(-1,-1); 
            }
 
            base.OnPreviewMouseRightButtonUp(e);
        }

 
        /// 
        ///     Fetches the value of the IsEnabled property 
        ///  
        /// 
        ///     The reason this property is overridden is so that ScrollBar 
        ///     could infuse the value for EnoughContentToScroll into it.
        /// 
        protected override bool IsEnabledCore
        { 
            get
            { 
                return base.IsEnabledCore && _canScroll; 
            }
        } 

        /// 
        /// ScrollBar locates the Track element when its visual tree is created
        ///  
        public override void OnApplyTemplate()
        { 
            base.OnApplyTemplate(); 
            _track = GetTemplateChild(TrackName) as Track;
        } 

        #endregion

        ///  
        /// Scroll content by one line to the top.
        ///  
        public static readonly RoutedCommand LineUpCommand = new RoutedCommand("LineUp", typeof(ScrollBar)); 
        /// 
        /// Scroll content by one line to the bottom. 
        /// 
        public static readonly RoutedCommand LineDownCommand = new RoutedCommand("LineDown", typeof(ScrollBar));
        /// 
        /// Scroll content by one line to the left. 
        /// 
        public static readonly RoutedCommand LineLeftCommand = new RoutedCommand("LineLeft", typeof(ScrollBar)); 
        ///  
        /// Scroll content by one line to the right.
        ///  
        public static readonly RoutedCommand LineRightCommand = new RoutedCommand("LineRight", typeof(ScrollBar));
        /// 
        /// Scroll content by one page to the top.
        ///  
        public static readonly RoutedCommand PageUpCommand = new RoutedCommand("PageUp", typeof(ScrollBar));
        ///  
        /// Scroll content by one page to the bottom. 
        /// 
        public static readonly RoutedCommand PageDownCommand = new RoutedCommand("PageDown", typeof(ScrollBar)); 
        /// 
        /// Scroll content by one page to the left.
        /// 
        public static readonly RoutedCommand PageLeftCommand = new RoutedCommand("PageLeft", typeof(ScrollBar)); 
        /// 
        /// Scroll content by one page to the right. 
        ///  
        public static readonly RoutedCommand PageRightCommand = new RoutedCommand("PageRight", typeof(ScrollBar));
        ///  
        /// Horizontally scroll to the beginning of the content.
        /// 
        public static readonly RoutedCommand ScrollToEndCommand = new RoutedCommand("ScrollToEnd", typeof(ScrollBar));
        ///  
        /// Horizontally scroll to the end of the content.
        ///  
        public static readonly RoutedCommand ScrollToHomeCommand = new RoutedCommand("ScrollToHome", typeof(ScrollBar)); 
        /// 
        /// Horizontally scroll to the beginning of the content. 
        /// 
        public static readonly RoutedCommand ScrollToRightEndCommand = new RoutedCommand("ScrollToRightEnd", typeof(ScrollBar));
        /// 
        /// Horizontally scroll to the end of the content. 
        /// 
        public static readonly RoutedCommand ScrollToLeftEndCommand = new RoutedCommand("ScrollToLeftEnd", typeof(ScrollBar)); 
        ///  
        /// Vertically scroll to the beginning of the content.
        ///  
        public static readonly RoutedCommand ScrollToTopCommand = new RoutedCommand("ScrollToTop", typeof(ScrollBar));
        /// 
        /// Vertically scroll to the end of the content.
        ///  
        public static readonly RoutedCommand ScrollToBottomCommand = new RoutedCommand("ScrollToBottom", typeof(ScrollBar));
        ///  
        /// Scrolls horizontally to the double value provided in . 
        /// 
        public static readonly RoutedCommand ScrollToHorizontalOffsetCommand = new RoutedCommand("ScrollToHorizontalOffset", typeof(ScrollBar)); 
        /// 
        /// Scrolls vertically to the double value provided in .
        /// 
        public static readonly RoutedCommand ScrollToVerticalOffsetCommand = new RoutedCommand("ScrollToVerticalOffset", typeof(ScrollBar)); 
        /// 
        /// Scrolls horizontally by dragging to the double value provided in . 
        ///  
        public static readonly RoutedCommand DeferScrollToHorizontalOffsetCommand = new RoutedCommand("DeferScrollToToHorizontalOffset", typeof(ScrollBar));
        ///  
        /// Scrolls vertically by dragging to the double value provided in .
        /// 
        public static readonly RoutedCommand DeferScrollToVerticalOffsetCommand = new RoutedCommand("DeferScrollToVerticalOffset", typeof(ScrollBar));
 
        /// 
        /// Scroll to the point where user invoke ScrollBar ContextMenu.  This command is always handled by ScrollBar. 
        ///  
        public static readonly RoutedCommand ScrollHereCommand = new RoutedCommand("ScrollHere", typeof(ScrollBar));
 

        //--------------------------------------------------------------------
        //
        //  Private Methods (and Event Handlers) 
        //
        //-------------------------------------------------------------------- 
 
        #region Private Methods
 
        private static void OnThumbDragStarted(object sender, DragStartedEventArgs e)
        {
            ScrollBar scrollBar = sender as ScrollBar;
            if (scrollBar == null) { return; } 

            scrollBar._hasScrolled = false; 
            scrollBar._previousValue = scrollBar.Value; 
        }
 
        // Event handler to listen to thumb events.
        private static void OnThumbDragDelta(object sender, DragDeltaEventArgs e)
        {
            ScrollBar scrollBar = sender as ScrollBar; 
            if (scrollBar == null) { return; }
 
            scrollBar.UpdateValue(e.HorizontalChange + scrollBar._thumbOffset.X, e.VerticalChange + scrollBar._thumbOffset.Y); 
        }
 
        // Update ScrollBar Value based on the Thumb drag delta.
        // Deal with pixel -> logical scrolling unit conversion, and restrict the value to within [Minimum, Maximum].
        private void UpdateValue(double horizontalDragDelta, double verticalDragDelta)
        { 
            if (Track != null)
            { 
                double valueDelta = Track.ValueFromDistance(horizontalDragDelta, verticalDragDelta); 
                if (    System.Windows.Shapes.Shape.IsDoubleFinite(valueDelta)
                    &&  !DoubleUtil.IsZero(valueDelta)) 
                {
                    double currentValue = Value;
                    double newValue = currentValue + valueDelta;
 
                    double perpendicularDragDelta;
 
                    // Compare distances from thumb for horizontal and vertical orientations 
                    if (Orientation == Orientation.Horizontal)
                    { 
                        perpendicularDragDelta = Math.Abs(verticalDragDelta);
                    }
                    else //Orientation == Orientation.Vertical
                    { 
                        perpendicularDragDelta = Math.Abs(horizontalDragDelta);
                    } 
 
                    if (DoubleUtil.GreaterThan(perpendicularDragDelta, MaxPerpendicularDelta))
                    { 
                        newValue = _previousValue;
                    }

                    if (!DoubleUtil.AreClose(currentValue, newValue)) 
                    {
                        _hasScrolled = true; 
                        ChangeValue(newValue, true /* defer */); 
                        RaiseScrollEvent(ScrollEventType.ThumbTrack);
                    } 
                }
            }
        }
 
        /// 
        /// Listen to Thumb DragCompleted event. 
        ///  
        /// 
        ///  
        private static void OnThumbDragCompleted(object sender, DragCompletedEventArgs e)
        {
            ((ScrollBar)sender).OnThumbDragCompleted(e);
        } 

        ///  
        /// Called when user dragging the Thumb. 
        /// This function can be override to customize the way Slider handles Thumb movement.
        ///  
        /// 
        private void OnThumbDragCompleted(DragCompletedEventArgs e)
        {
            if (_hasScrolled) 
            {
                FinishDrag(); 
                RaiseScrollEvent(ScrollEventType.EndScroll); 
            }
        } 

        private IInputElement CommandTarget
        {
            get 
            {
                IInputElement target = TemplatedParent as IInputElement; 
                if (target == null) 
                {
                    target = this; 
                }

                return target;
            } 
        }
 
        private void FinishDrag() 
        {
            double value = Value; 
            IInputElement target = CommandTarget;
            RoutedCommand command = (Orientation == Orientation.Horizontal) ? DeferScrollToHorizontalOffsetCommand : DeferScrollToVerticalOffsetCommand;

            if (command.CanExecute(value, target)) 
            {
                // If we were reporting drag commands, we need to give a final scroll command 
                ChangeValue(value, false /* defer */); 
            }
        } 


        private void ChangeValue(double newValue, bool defer)
        { 
            newValue = Math.Min(Math.Max(newValue, Minimum), Maximum);
            if (IsStandalone) { Value = newValue; } 
            else 
            {
                IInputElement target = CommandTarget; 
                RoutedCommand command = null;
                bool horizontal = (Orientation == Orientation.Horizontal);

                // Fire the deferred (drag) version of the command 
                if (defer)
                { 
                    command = horizontal ? DeferScrollToHorizontalOffsetCommand : DeferScrollToVerticalOffsetCommand; 
                    if (command.CanExecute(newValue, target))
                    { 
                        // The defer version of the command is enabled, fire this command and not the scroll version
                        command.Execute(newValue, target);
                    }
                    else 
                    {
                        // The defer version of the command is not enabled, reset and try the scroll version 
                        command = null; 
                    }
                } 

                if (command == null)
                {
                    // Either we're not dragging or the drag command is not enabled, try the scroll version 
                    command = horizontal ? ScrollToHorizontalOffsetCommand : ScrollToVerticalOffsetCommand;
                    if (command.CanExecute(newValue, target)) 
                    { 
                        command.Execute(newValue, target);
                    } 
                }
            }
        }
 
        /// 
        /// Scroll to the position where ContextMenu was invoked. 
        ///  
        internal void ScrollToLastMousePoint()
        { 
            Point pt = new Point(-1,-1);
            if ((Track != null) && (_latestRightButtonClickPoint != pt))
            {
                double newValue = Track.ValueFromPoint(_latestRightButtonClickPoint); 
                if (System.Windows.Shapes.Shape.IsDoubleFinite(newValue))
                { 
                    ChangeValue(newValue, false /* defer */); 
                    _latestRightButtonClickPoint = pt;
                    RaiseScrollEvent(ScrollEventType.ThumbPosition); 
                }
            }
        }
 
        internal void RaiseScrollEvent(ScrollEventType scrollEventType)
        { 
            ScrollEventArgs newEvent = new ScrollEventArgs(scrollEventType, Value); 
            newEvent.Source=this;
            RaiseEvent(newEvent); 
        }

        private static void OnScrollCommand(object target, ExecutedRoutedEventArgs args)
        { 
            ScrollBar scrollBar = ((ScrollBar)target);
            if (args.Command == ScrollBar.ScrollHereCommand) 
            { 
                scrollBar.ScrollToLastMousePoint();
            } 

            if (scrollBar.IsStandalone)
            {
                if (scrollBar.Orientation == Orientation.Vertical) 
                {
                    if (args.Command == ScrollBar.LineUpCommand) 
                    { 
                        scrollBar.LineUp();
                    } 
                    else if (args.Command == ScrollBar.LineDownCommand)
                    {
                        scrollBar.LineDown();
                    } 
                    else if (args.Command == ScrollBar.PageUpCommand)
                    { 
                        scrollBar.PageUp(); 
                    }
                    else if (args.Command == ScrollBar.PageDownCommand) 
                    {
                        scrollBar.PageDown();
                    }
                    else if (args.Command == ScrollBar.ScrollToTopCommand) 
                    {
                        scrollBar.ScrollToTop(); 
                    } 
                    else if (args.Command == ScrollBar.ScrollToBottomCommand)
                    { 
                        scrollBar.ScrollToBottom();
                    }
                }
                else //Horizontal 
                {
                    if (args.Command == ScrollBar.LineLeftCommand) 
                    { 
                        scrollBar.LineLeft();
                    } 
                    else if (args.Command == ScrollBar.LineRightCommand)
                    {
                        scrollBar.LineRight();
                    } 
                    else if (args.Command == ScrollBar.PageLeftCommand)
                    { 
                        scrollBar.PageLeft(); 
                    }
                    else if (args.Command == ScrollBar.PageRightCommand) 
                    {
                        scrollBar.PageRight();
                    }
                    else if (args.Command == ScrollBar.ScrollToLeftEndCommand) 
                    {
                        scrollBar.ScrollToLeftEnd(); 
                    } 
                    else if (args.Command == ScrollBar.ScrollToRightEndCommand)
                    { 
                        scrollBar.ScrollToRightEnd();
                    }
                }
            } 
        }
 
        private void SmallDecrement() 
        {
            double newValue = Math.Max(Value - SmallChange, Minimum); 
            if (Value != newValue)
            {
                Value = newValue;
                RaiseScrollEvent(ScrollEventType.SmallDecrement); 
            }
        } 
        private void SmallIncrement() 
        {
            double newValue = Math.Min(Value + SmallChange, Maximum); 
            if (Value != newValue)
            {
                Value = newValue;
                RaiseScrollEvent(ScrollEventType.SmallIncrement); 
            }
        } 
        private void LargeDecrement() 
        {
            double newValue = Math.Max(Value - LargeChange, Minimum); 
            if (Value != newValue)
            {
                Value = newValue;
                RaiseScrollEvent(ScrollEventType.LargeDecrement); 
            }
        } 
        private void LargeIncrement() 
        {
            double newValue = Math.Min(Value + LargeChange, Maximum); 
            if (Value != newValue)
            {
                Value = newValue;
                RaiseScrollEvent(ScrollEventType.LargeIncrement); 
            }
        } 
        private void ToMinimum() 
        {
            if (Value != Minimum) 
            {
                Value = Minimum;
                RaiseScrollEvent(ScrollEventType.First);
            } 
        }
        private void ToMaximum() 
        { 
            if (Value != Maximum)
            { 
                Value = Maximum;
                RaiseScrollEvent(ScrollEventType.Last);
            }
        } 
        private void LineUp()
        { 
            SmallDecrement(); 
        }
        private void LineDown() 
        {
            SmallIncrement();
        }
        private void PageUp() 
        {
            LargeDecrement(); 
        } 
        private void PageDown()
        { 
            LargeIncrement();
        }
        private void ScrollToTop()
        { 
            ToMinimum();
        } 
        private void ScrollToBottom() 
        {
            ToMaximum(); 
        }
        private void LineLeft()
        {
            SmallDecrement(); 
        }
        private void LineRight() 
        { 
            SmallIncrement();
        } 
        private void PageLeft()
        {
            LargeDecrement();
        } 
        private void PageRight()
        { 
            LargeIncrement(); 
        }
        private void ScrollToLeftEnd() 
        {
            ToMinimum();
        }
        private void ScrollToRightEnd() 
        {
            ToMaximum(); 
        } 

        private static void OnQueryScrollHereCommand(object target, CanExecuteRoutedEventArgs args) 
        {
            args.CanExecute = (args.Command == ScrollBar.ScrollHereCommand);
        }
 
        private static void OnQueryScrollCommand(object target, CanExecuteRoutedEventArgs args)
        { 
            args.CanExecute = ((ScrollBar)target).IsStandalone; 
        }
 
        #endregion

        //-------------------------------------------------------------------
        // 
        //  Private Members
        // 
        //-------------------------------------------------------------------- 

        #region Private Members 

        #endregion

        //------------------------------------------------------------------- 
        //
        //  Static Constructor & Delegates 
        // 
        //-------------------------------------------------------------------
 
        #region Static Constructor & Delegates

        static ScrollBar()
        { 
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ScrollBar), new FrameworkPropertyMetadata(typeof(ScrollBar)));
            _dType = DependencyObjectType.FromSystemTypeInternal(typeof(ScrollBar)); 
 
            var onScrollCommand = new ExecutedRoutedEventHandler(OnScrollCommand);
            var onQueryScrollCommand = new CanExecuteRoutedEventHandler(OnQueryScrollCommand); 

            FocusableProperty.OverrideMetadata(typeof(ScrollBar), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox));

            // Register Event Handler for the Thumb 
            EventManager.RegisterClassHandler(typeof(ScrollBar), Thumb.DragStartedEvent, new DragStartedEventHandler(OnThumbDragStarted));
            EventManager.RegisterClassHandler(typeof(ScrollBar), Thumb.DragDeltaEvent, new DragDeltaEventHandler(OnThumbDragDelta)); 
            EventManager.RegisterClassHandler(typeof(ScrollBar), Thumb.DragCompletedEvent, new DragCompletedEventHandler(OnThumbDragCompleted)); 

            // ScrollBar has common handler for ScrollHere command. 
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.ScrollHereCommand, onScrollCommand, new CanExecuteRoutedEventHandler(OnQueryScrollHereCommand));
            // Vertical Commands
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.LineUpCommand, onScrollCommand, onQueryScrollCommand, Key.Up);
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.LineDownCommand, onScrollCommand, onQueryScrollCommand, Key.Down); 
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.PageUpCommand, onScrollCommand, onQueryScrollCommand, Key.PageUp);
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.PageDownCommand, onScrollCommand, onQueryScrollCommand, Key.PageDown); 
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.ScrollToTopCommand, onScrollCommand, onQueryScrollCommand, new KeyGesture(Key.Home, ModifierKeys.Control)); 
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.ScrollToBottomCommand, onScrollCommand, onQueryScrollCommand, new KeyGesture(Key.End, ModifierKeys.Control));
            // Horizontal Commands 
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.LineLeftCommand, onScrollCommand, onQueryScrollCommand, Key.Left);
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.LineRightCommand, onScrollCommand, onQueryScrollCommand, Key.Right);
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.PageLeftCommand, onScrollCommand, onQueryScrollCommand);
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.PageRightCommand, onScrollCommand, onQueryScrollCommand); 
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.ScrollToLeftEndCommand, onScrollCommand, onQueryScrollCommand, Key.Home);
            CommandHelpers.RegisterCommandHandler(typeof(ScrollBar), ScrollBar.ScrollToRightEndCommand, onScrollCommand, onQueryScrollCommand, Key.End); 
 
            MaximumProperty.OverrideMetadata(typeof(ScrollBar), new FrameworkPropertyMetadata(new PropertyChangedCallback(ViewChanged)));
            MinimumProperty.OverrideMetadata(typeof(ScrollBar), new FrameworkPropertyMetadata(new PropertyChangedCallback(ViewChanged))); 

            ContextMenuProperty.OverrideMetadata(typeof(ScrollBar), new FrameworkPropertyMetadata(null, new CoerceValueCallback(CoerceContextMenu)));
        }
 
        private static void ViewChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            ScrollBar scrollBar = (ScrollBar)d; 

            bool canScrollNew = scrollBar.Maximum > scrollBar.Minimum; 

            if (canScrollNew != scrollBar._canScroll)
            {
                scrollBar._canScroll = canScrollNew; 
                scrollBar.CoerceValue(IsEnabledProperty);
            } 
        } 

        // Consider adding a verify for ViewportSize to check > 0.0 

        internal static bool IsValidOrientation(object o)
        {
            Orientation value = (Orientation)o; 
            return value == Orientation.Horizontal
                || value == Orientation.Vertical; 
        } 

        // Is the scrollbar outside of a scrollviewer? 
        internal bool IsStandalone
        {
            get { return _isStandalone; }
            set { _isStandalone = value; } 
        }
 
        // Maximum distance you can drag from thumb before it snaps back 
        private const double MaxPerpendicularDelta = 150;
        private const string TrackName = "PART_Track"; 

        private Track _track;

        private Point _latestRightButtonClickPoint = new Point(-1,-1); 

        private bool _canScroll = true;  // Maximum > Minimum by default 
        private bool _hasScrolled;  // Has the thumb been dragged 
        private bool _isStandalone = true;
        private bool _openingContextMenu; 
        private double _previousValue;
        private Vector _thumbOffset;

 

        #endregion 
 

        #region DTypeThemeStyleKey 

        // Returns the DependencyObjectType for the registered ThemeStyleKey's default
        // value. Controls will override this method to return approriate types.
        internal override DependencyObjectType DTypeThemeStyleKey 
        {
            get { return _dType; } 
        } 

        private static DependencyObjectType _dType; 

        #endregion DTypeThemeStyleKey

        #region ContextMenu 

        private static object CoerceContextMenu(DependencyObject o, object value) 
        { 
            bool hasModifiers;
            ScrollBar sb = (ScrollBar)o; 
            if (sb._openingContextMenu &&
                sb.GetValueSource(ContextMenuProperty, null, out hasModifiers) == BaseValueSourceInternal.Default && !hasModifiers)
            {
                // Use a default menu 
                if (sb.Orientation == Orientation.Vertical)
                { 
                    return VerticalContextMenu; 
                }
                else if (sb.FlowDirection == FlowDirection.LeftToRight) 
                {
                    return HorizontalContextMenuLTR;
                }
                else 
                {
                    return HorizontalContextMenuRTL; 
                } 
            }
            return value; 
        }

        /// 
        ///     Called when ContextMenuOpening is raised on this element. 
        /// 
        /// Event arguments 
        protected override void OnContextMenuOpening(ContextMenuEventArgs e) 
        {
            base.OnContextMenuOpening(e); 

            if (!e.Handled)
            {
                _openingContextMenu = true; 
                CoerceValue(ContextMenuProperty);
            } 
        } 

        ///  
        ///     Called when ContextMenuOpening is raised on this element.
        /// 
        /// Event arguments
        protected override void OnContextMenuClosing(ContextMenuEventArgs e) 
        {
            base.OnContextMenuClosing(e); 
 
            _openingContextMenu = false;
            CoerceValue(ContextMenuProperty); 
        }

        private static ContextMenu VerticalContextMenu
        { 
            get
            { 
                ContextMenu verticalContextMenu = new ContextMenu(); 
                verticalContextMenu.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_ScrollHere, "ScrollHere", ScrollBar.ScrollHereCommand));
                verticalContextMenu.Items.Add(new Separator()); 
                verticalContextMenu.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_Top, "Top", ScrollBar.ScrollToTopCommand));
                verticalContextMenu.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_Bottom, "Bottom", ScrollBar.ScrollToBottomCommand));
                verticalContextMenu.Items.Add(new Separator());
                verticalContextMenu.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_PageUp, "PageUp", ScrollBar.PageUpCommand)); 
                verticalContextMenu.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_PageDown, "PageDown", ScrollBar.PageDownCommand));
                verticalContextMenu.Items.Add(new Separator()); 
                verticalContextMenu.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_ScrollUp, "ScrollUp", ScrollBar.LineUpCommand)); 
                verticalContextMenu.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_ScrollDown, "ScrollDown", ScrollBar.LineDownCommand));
                return verticalContextMenu; 
            }
        }

        // LeftToRight menu 
        private static ContextMenu HorizontalContextMenuLTR
        { 
            get 
            {
                ContextMenu horizontalContextMenuLeftToRight = new ContextMenu(); 
                horizontalContextMenuLeftToRight.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_ScrollHere, "ScrollHere", ScrollBar.ScrollHereCommand));
                horizontalContextMenuLeftToRight.Items.Add(new Separator());
                horizontalContextMenuLeftToRight.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_LeftEdge, "LeftEdge", ScrollBar.ScrollToLeftEndCommand));
                horizontalContextMenuLeftToRight.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_RightEdge, "RightEdge", ScrollBar.ScrollToRightEndCommand)); 
                horizontalContextMenuLeftToRight.Items.Add(new Separator());
                horizontalContextMenuLeftToRight.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_PageLeft, "PageLeft", ScrollBar.PageLeftCommand)); 
                horizontalContextMenuLeftToRight.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_PageRight, "PageRight", ScrollBar.PageRightCommand)); 
                horizontalContextMenuLeftToRight.Items.Add(new Separator());
                horizontalContextMenuLeftToRight.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_ScrollLeft, "ScrollLeft", ScrollBar.LineLeftCommand)); 
                horizontalContextMenuLeftToRight.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_ScrollRight, "ScrollRight", ScrollBar.LineRightCommand));
                return horizontalContextMenuLeftToRight;
            }
        } 

        // RightToLeft menu 
        private static ContextMenu HorizontalContextMenuRTL 
        {
            get 
            {
                ContextMenu horizontalContextMenuRightToLeft = new ContextMenu();
                horizontalContextMenuRightToLeft.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_ScrollHere, "ScrollHere", ScrollBar.ScrollHereCommand));
                horizontalContextMenuRightToLeft.Items.Add(new Separator()); 
                horizontalContextMenuRightToLeft.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_LeftEdge, "LeftEdge", ScrollBar.ScrollToRightEndCommand));
                horizontalContextMenuRightToLeft.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_RightEdge, "RightEdge", ScrollBar.ScrollToLeftEndCommand)); 
                horizontalContextMenuRightToLeft.Items.Add(new Separator()); 
                horizontalContextMenuRightToLeft.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_PageLeft, "PageLeft", ScrollBar.PageRightCommand));
                horizontalContextMenuRightToLeft.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_PageRight, "PageRight", ScrollBar.PageLeftCommand)); 
                horizontalContextMenuRightToLeft.Items.Add(new Separator());
                horizontalContextMenuRightToLeft.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_ScrollLeft, "ScrollLeft", ScrollBar.LineRightCommand));
                horizontalContextMenuRightToLeft.Items.Add(CreateMenuItem(SRID.ScrollBar_ContextMenu_ScrollRight, "ScrollRight", ScrollBar.LineLeftCommand));
                return horizontalContextMenuRightToLeft; 
            }
        } 
 
        private static MenuItem CreateMenuItem(string name, string automationId, RoutedCommand command)
        { 
            MenuItem menuItem = new MenuItem();
            menuItem.Header = SR.Get(name);
            menuItem.Command = command;
            AutomationProperties.SetAutomationId(menuItem, automationId); 

            Binding binding = new Binding(); 
            binding.Path = new PropertyPath(ContextMenu.PlacementTargetProperty); 
            binding.Mode = BindingMode.OneWay;
            binding.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(ContextMenu), 1); 
            menuItem.SetBinding(MenuItem.CommandTargetProperty, binding);

            return menuItem;
        } 

        // 
        //  This property 
        //  1. Finds the correct initial size for the _effectiveValues store on the current DependencyObject
        //  2. This is a performance optimization 
        //
        internal override int EffectiveValuesInitialSize
        {
            get { return 42; } 
        }
 
        #endregion ContextMenu 
    }
 
    /// 
    /// Type of scrolling that causes ScrollEvent.
    /// 
    public enum ScrollEventType 
    {
        ///  
        /// Thumb has stopped moving. 
        /// 
        EndScroll, 
        /// 
        /// Thumb was moved to the Minimum position.
        /// 
        First, 
        /// 
        /// Thumb was moved a large distance. The user clicked the scroll bar to the left(horizontal) or above(vertical) the scroll box. 
        ///  
        LargeDecrement,
        ///  
        /// Thumb was moved a large distance. The user clicked the scroll bar to the right(horizontal) or below(vertical) the scroll box.
        /// 
        LargeIncrement,
        ///  
        /// Thumb was moved to the Maximum position
        ///  
        Last, 
        /// 
        /// Thumb was moved a small distance. The user clicked the left(horizontal) or top(vertical) scroll arrow. 
        /// 
        SmallDecrement,
        /// 
        /// Thumb was moved a small distance. The user clicked the right(horizontal) or bottom(vertical) scroll arrow. 
        /// 
        SmallIncrement, 
        ///  
        /// Thumb was moved.
        ///  
        ThumbPosition,
        /// 
        /// Thumb is currently being moved.
        ///  
        ThumbTrack
    } 
 
}
 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK