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 public Orientation Orientation { get { return (Orientation) GetValue(OrientationProperty); } set { SetValue(OrientationProperty, value); } } ///: Vertical or Horizontal. /// On vertical ScrollBars, the thumb moves up and down. On horizontal bars, the thumb moves left to right. /// /// ViewportSize is the amount of the scrolled extent currently visible. For most scrolled content, this value /// will be bound to one of [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public double ViewportSize { get { return (double)GetValue(ViewportSizeProperty); } set { SetValue(ViewportSizeProperty, value); } } ///'s ViewportSize properties. /// This property is in logical scrolling units. /// /// DependencyProperty for public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register("Orientation", typeof(Orientation), typeof(ScrollBar), new FrameworkPropertyMetadata(Orientation.Vertical), new ValidateValueCallback(IsValidOrientation)); ///property. /// /// DependencyProperty for public static readonly DependencyProperty ViewportSizeProperty = DependencyProperty.Register("ViewportSize", typeof(double), typeof(ScrollBar), new FrameworkPropertyMetadata(0.0d), new ValidateValueCallback(System.Windows.Shapes.Shape.IsDoubleFiniteNonNegative)); ///property. /// /// 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 public Orientation Orientation { get { return (Orientation) GetValue(OrientationProperty); } set { SetValue(OrientationProperty, value); } } ///: Vertical or Horizontal. /// On vertical ScrollBars, the thumb moves up and down. On horizontal bars, the thumb moves left to right. /// /// ViewportSize is the amount of the scrolled extent currently visible. For most scrolled content, this value /// will be bound to one of [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public double ViewportSize { get { return (double)GetValue(ViewportSizeProperty); } set { SetValue(ViewportSizeProperty, value); } } ///'s ViewportSize properties. /// This property is in logical scrolling units. /// /// DependencyProperty for public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register("Orientation", typeof(Orientation), typeof(ScrollBar), new FrameworkPropertyMetadata(Orientation.Vertical), new ValidateValueCallback(IsValidOrientation)); ///property. /// /// DependencyProperty for public static readonly DependencyProperty ViewportSizeProperty = DependencyProperty.Register("ViewportSize", typeof(double), typeof(ScrollBar), new FrameworkPropertyMetadata(0.0d), new ValidateValueCallback(System.Windows.Shapes.Shape.IsDoubleFiniteNonNegative)); ///property. /// /// 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

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Membership.cs
- CodeTypeOfExpression.cs
- FigureParagraph.cs
- ExpandCollapseProviderWrapper.cs
- DropSource.cs
- BeginStoryboard.cs
- XmlSchemaObjectTable.cs
- ReliabilityContractAttribute.cs
- BackgroundWorker.cs
- IdnElement.cs
- TableColumn.cs
- InputProcessorProfiles.cs
- StrokeNode.cs
- CodeDOMUtility.cs
- EntityViewGenerator.cs
- CallbackValidator.cs
- TraceUtility.cs
- ClientBuildManager.cs
- SqlNodeTypeOperators.cs
- MaskInputRejectedEventArgs.cs
- basevalidator.cs
- ConsumerConnectionPoint.cs
- HyperLinkStyle.cs
- SchemaHelper.cs
- Parameter.cs
- NumericUpDown.cs
- DriveInfo.cs
- PersonalizableAttribute.cs
- ControlHelper.cs
- DisplayNameAttribute.cs
- MostlySingletonList.cs
- BufferedWebEventProvider.cs
- CheckBox.cs
- PrintDocument.cs
- Char.cs
- XmlAttributeAttribute.cs
- GridEntry.cs
- LinkArea.cs
- LineVisual.cs
- RelationshipConstraintValidator.cs
- TemplateXamlParser.cs
- TextEditorTables.cs
- DurableTimerExtension.cs
- EnumerableRowCollectionExtensions.cs
- AnnotationComponentChooser.cs
- DefaultCommandConverter.cs
- BufferModesCollection.cs
- StrokeCollection.cs
- SafeRightsManagementHandle.cs
- SizeLimitedCache.cs
- WindowsToolbarAsMenu.cs
- InstanceStoreQueryResult.cs
- UnsafeMethods.cs
- XmlDataSourceView.cs
- UIntPtr.cs
- PointCollectionValueSerializer.cs
- __ConsoleStream.cs
- XPathQilFactory.cs
- WebPermission.cs
- HeaderLabel.cs
- PriorityRange.cs
- AspNetSynchronizationContext.cs
- UInt16.cs
- GACIdentityPermission.cs
- GeneratedContractType.cs
- SymbolTable.cs
- HttpValueCollection.cs
- PropertyEmitterBase.cs
- ScheduleChanges.cs
- MouseWheelEventArgs.cs
- AngleUtil.cs
- LineMetrics.cs
- ControlDesignerState.cs
- XmlObjectSerializerReadContext.cs
- DataGridViewComboBoxEditingControl.cs
- SolidColorBrush.cs
- DesignerTransactionCloseEvent.cs
- InsufficientMemoryException.cs
- MdiWindowListStrip.cs
- DataShape.cs
- PagerSettings.cs
- ActionFrame.cs
- OleDbException.cs
- ThrowHelper.cs
- StandardBindingOptionalReliableSessionElement.cs
- ModelTreeEnumerator.cs
- BuilderPropertyEntry.cs
- Attributes.cs
- CustomTypeDescriptor.cs
- StylusDevice.cs
- TraceContext.cs
- DataTableTypeConverter.cs
- SqlFacetAttribute.cs
- ComponentCollection.cs
- PlacementWorkspace.cs
- SignedXmlDebugLog.cs
- PreservationFileWriter.cs
- FormatConvertedBitmap.cs
- ResourceSet.cs
- MultipartIdentifier.cs