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 / Slider.cs / 1 / Slider.cs
//----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Collections;
using System.Windows.Threading;
using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using MS.Win32;
using MS.Internal;
using MS.Internal.Commands;
// For typeconverter
using System.ComponentModel.Design.Serialization;
using System.Reflection;
namespace System.Windows.Controls
{
///
/// Slider control lets the user select from a range of values by moving a slider.
/// Slider is used to enable to user to gradually modify a value (range selection).
/// Slider is an easy and natural interface for users, because it provides good visual feedback.
///
///
[Localizability(LocalizationCategory.Ignore)]
[DefaultEvent("ValueChanged"), DefaultProperty("Value")]
[TemplatePart(Name = "PART_Track", Type = typeof(Track))]
[TemplatePart(Name = "PART_SelectionRange", Type = typeof(FrameworkElement))]
public class Slider : RangeBase
{
#region Constructors
///
/// Instantiates a new instance of a Slider with out Dispatcher.
///
///
public Slider() : base()
{
}
///
/// This is the static constructor for the Slider class. It
/// simply registers the appropriate class handlers for the input
/// devices, and defines a default style sheet.
///
static Slider()
{
// Initialize CommandCollection & CommandLink(s)
InitializeCommands();
// Register all PropertyTypeMetadata
MinimumProperty.OverrideMetadata(typeof(Slider), new FrameworkPropertyMetadata(0.0d, FrameworkPropertyMetadataOptions.AffectsMeasure));
MaximumProperty.OverrideMetadata(typeof(Slider), new FrameworkPropertyMetadata(10.0d, FrameworkPropertyMetadataOptions.AffectsMeasure));
ValueProperty.OverrideMetadata(typeof(Slider), new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsMeasure));
// Register Event Handler for the Thumb
EventManager.RegisterClassHandler(typeof(Slider), Thumb.DragStartedEvent, new DragStartedEventHandler(Slider.OnThumbDragStarted));
EventManager.RegisterClassHandler(typeof(Slider), Thumb.DragDeltaEvent, new DragDeltaEventHandler(Slider.OnThumbDragDelta));
EventManager.RegisterClassHandler(typeof(Slider), Thumb.DragCompletedEvent, new DragCompletedEventHandler(Slider.OnThumbDragCompleted));
// Listen to MouseLeftButtonDown event to determine if slide should move focus to itself
EventManager.RegisterClassHandler(typeof(Slider), Mouse.MouseDownEvent, new MouseButtonEventHandler(Slider._OnMouseLeftButtonDown),true);
DefaultStyleKeyProperty.OverrideMetadata(typeof(Slider), new FrameworkPropertyMetadata(typeof(Slider)));
_dType = DependencyObjectType.FromSystemTypeInternal(typeof(Slider));
}
#endregion Constructors
#region Commands
private static RoutedCommand _increaseLargeCommand = null;
private static RoutedCommand _increaseSmallCommand = null;
private static RoutedCommand _decreaseLargeCommand = null;
private static RoutedCommand _decreaseSmallCommand = null;
private static RoutedCommand _minimizeValueCommand = null;
private static RoutedCommand _maximizeValueCommand = null;
///
/// Increase Slider value
///
public static RoutedCommand IncreaseLarge
{
get { return _increaseLargeCommand; }
}
///
/// Decrease Slider value
///
public static RoutedCommand DecreaseLarge
{
get { return _decreaseLargeCommand; }
}
///
/// Increase Slider value
///
public static RoutedCommand IncreaseSmall
{
get { return _increaseSmallCommand; }
}
///
/// Decrease Slider value
///
public static RoutedCommand DecreaseSmall
{
get { return _decreaseSmallCommand; }
}
///
/// Set Slider value to mininum
///
public static RoutedCommand MinimizeValue
{
get { return _minimizeValueCommand; }
}
///
/// Set Slider value to maximum
///
public static RoutedCommand MaximizeValue
{
get { return _maximizeValueCommand; }
}
static void InitializeCommands()
{
_increaseLargeCommand = new RoutedCommand("IncreaseLarge", typeof(Slider));
_decreaseLargeCommand = new RoutedCommand("DecreaseLarge", typeof(Slider));
_increaseSmallCommand = new RoutedCommand("IncreaseSmall", typeof(Slider));
_decreaseSmallCommand = new RoutedCommand("DecreaseSmall", typeof(Slider));
_minimizeValueCommand = new RoutedCommand("MinimizeValue", typeof(Slider));
_maximizeValueCommand = new RoutedCommand("MaximizeValue", typeof(Slider));
CommandHelpers.RegisterCommandHandler(typeof(Slider), _increaseLargeCommand, new ExecutedRoutedEventHandler(OnIncreaseLargeCommand),
new SliderGesture(Key.PageUp, Key.PageDown, false));
CommandHelpers.RegisterCommandHandler(typeof(Slider), _decreaseLargeCommand, new ExecutedRoutedEventHandler(OnDecreaseLargeCommand),
new SliderGesture(Key.PageDown, Key.PageUp, false));
CommandHelpers.RegisterCommandHandler(typeof(Slider), _increaseSmallCommand, new ExecutedRoutedEventHandler(OnIncreaseSmallCommand),
new SliderGesture(Key.Up, Key.Down, false),
new SliderGesture(Key.Right, Key.Left, true));
CommandHelpers.RegisterCommandHandler(typeof(Slider), _decreaseSmallCommand, new ExecutedRoutedEventHandler(OnDecreaseSmallCommand),
new SliderGesture(Key.Down, Key.Up, false),
new SliderGesture(Key.Left, Key.Right, true));
CommandHelpers.RegisterCommandHandler(typeof(Slider), _minimizeValueCommand, new ExecutedRoutedEventHandler(OnMinimizeValueCommand),
Key.Home);
CommandHelpers.RegisterCommandHandler(typeof(Slider), _maximizeValueCommand, new ExecutedRoutedEventHandler(OnMaximizeValueCommand),
Key.End);
}
private class SliderGesture : InputGesture
{
public SliderGesture(Key normal, Key inverted, bool forHorizontal)
{
_normal = normal;
_inverted = inverted;
_forHorizontal = forHorizontal;
}
///
/// Sees if the InputGesture matches the input associated with the inputEventArgs
///
public override bool Matches(object targetElement, InputEventArgs inputEventArgs)
{
KeyEventArgs keyEventArgs = inputEventArgs as KeyEventArgs;
Slider slider = targetElement as Slider;
if (keyEventArgs != null && slider != null && Keyboard.Modifiers == ModifierKeys.None)
{
if((int)_normal == (int)keyEventArgs.RealKey)
{
return !IsInverted(slider);
}
if ((int)_inverted == (int)keyEventArgs.RealKey)
{
return IsInverted(slider);
}
}
return false;
}
private bool IsInverted(Slider slider)
{
if (_forHorizontal)
{
return slider.IsDirectionReversed != (slider.FlowDirection == FlowDirection.RightToLeft);
}
else
{
return slider.IsDirectionReversed;
}
}
private Key _normal, _inverted;
private bool _forHorizontal;
}
private static void OnIncreaseSmallCommand(object sender, ExecutedRoutedEventArgs e)
{
Slider slider = sender as Slider;
if (slider != null)
{
slider.OnIncreaseSmall();
}
}
private static void OnDecreaseSmallCommand(object sender, ExecutedRoutedEventArgs e)
{
Slider slider = sender as Slider;
if (slider != null)
{
slider.OnDecreaseSmall();
}
}
private static void OnMaximizeValueCommand(object sender, ExecutedRoutedEventArgs e)
{
Slider slider = sender as Slider;
if (slider != null)
{
slider.OnMaximizeValue();
}
}
private static void OnMinimizeValueCommand(object sender, ExecutedRoutedEventArgs e)
{
Slider slider = sender as Slider;
if (slider != null)
{
slider.OnMinimizeValue();
}
}
private static void OnIncreaseLargeCommand(object sender, ExecutedRoutedEventArgs e)
{
Slider slider = sender as Slider;
if (slider != null)
{
slider.OnIncreaseLarge();
}
}
private static void OnDecreaseLargeCommand(object sender, ExecutedRoutedEventArgs e)
{
Slider slider = sender as Slider;
if (slider != null)
{
slider.OnDecreaseLarge();
}
}
#endregion Commands
#region Properties
#region Orientation Property
///
/// DependencyProperty for property.
///
public static readonly DependencyProperty OrientationProperty =
DependencyProperty.Register("Orientation", typeof(Orientation), typeof(Slider),
new FrameworkPropertyMetadata(Orientation.Horizontal),
new ValidateValueCallback(ScrollBar.IsValidOrientation));
///
/// Get/Set Orientation property
///
public Orientation Orientation
{
get { return (Orientation)GetValue(OrientationProperty); }
set { SetValue(OrientationProperty, value); }
}
#endregion
#region IsDirectionReversed Property
///
/// Slider ThumbProportion property
///
public static readonly DependencyProperty IsDirectionReversedProperty
= DependencyProperty.Register("IsDirectionReversed", typeof(bool), typeof(Slider),
new FrameworkPropertyMetadata(false));
///
/// Get/Set IsDirectionReversed property
///
[Bindable(true), Category("Appearance")]
public bool IsDirectionReversed
{
get
{
return (bool)GetValue(IsDirectionReversedProperty);
}
set
{
SetValue(IsDirectionReversedProperty, value);
}
}
#endregion
#region Delay Property
///
/// The Property for the Delay property.
///
public static readonly DependencyProperty DelayProperty = RepeatButton.DelayProperty.AddOwner(typeof(Slider), new FrameworkPropertyMetadata(RepeatButton.GetKeyboardDelay()));
///
/// Specifies the amount of time, in milliseconds, to wait before repeating begins.
/// Must be non-negative.
///
[Bindable(true), Category("Behavior")]
public int Delay
{
get
{
return (int)GetValue(DelayProperty);
}
set
{
SetValue(DelayProperty, value);
}
}
#endregion Delay Property
#region Interval Property
///
/// The Property for the Interval property.
///
public static readonly DependencyProperty IntervalProperty = RepeatButton.IntervalProperty.AddOwner(typeof(Slider), new FrameworkPropertyMetadata(RepeatButton.GetKeyboardSpeed()));
///
/// Specifies the amount of time, in milliseconds, between repeats once repeating starts.
/// Must be non-negative
///
[Bindable(true), Category("Behavior")]
public int Interval
{
get
{
return (int)GetValue(IntervalProperty);
}
set
{
SetValue(IntervalProperty, value);
}
}
#endregion Interval Property
#region AutoToolTipPlacement Property
///
/// The DependencyProperty for the AutoToolTipPlacement property.
///
public static readonly DependencyProperty AutoToolTipPlacementProperty
= DependencyProperty.Register("AutoToolTipPlacement", typeof(AutoToolTipPlacement), typeof(Slider),
new FrameworkPropertyMetadata(Primitives.AutoToolTipPlacement.None),
new ValidateValueCallback(IsValidAutoToolTipPlacement));
///
/// AutoToolTipPlacement property specifies the placement of the AutoToolTip
///
[Bindable(true), Category("Behavior")]
public Primitives.AutoToolTipPlacement AutoToolTipPlacement
{
get
{
return (Primitives.AutoToolTipPlacement)GetValue(AutoToolTipPlacementProperty);
}
set
{
SetValue(AutoToolTipPlacementProperty, value);
}
}
private static bool IsValidAutoToolTipPlacement(object o)
{
AutoToolTipPlacement placement = (AutoToolTipPlacement)o;
return placement == AutoToolTipPlacement.None ||
placement == AutoToolTipPlacement.TopLeft ||
placement == AutoToolTipPlacement.BottomRight;
}
#endregion
#region AutoToolTipPrecision Property
///
/// The DependencyProperty for the AutoToolTipPrecision property.
/// Flags: None
/// Default Value: 0
///
public static readonly DependencyProperty AutoToolTipPrecisionProperty
= DependencyProperty.Register("AutoToolTipPrecision", typeof(int), typeof(Slider),
new FrameworkPropertyMetadata(0), new ValidateValueCallback(IsValidAutoToolTipPrecision));
///
/// Get or set number of decimal digits of Slider's Value shown in AutoToolTip
///
[Bindable(true), Category("Appearance")]
public int AutoToolTipPrecision
{
get
{
return (int)GetValue(AutoToolTipPrecisionProperty);
}
set
{
SetValue(AutoToolTipPrecisionProperty, value);
}
}
///
/// Validates AutoToolTipPrecision value
///
///
///
private static bool IsValidAutoToolTipPrecision(object o)
{
return (((int)o) >= 0);
}
#endregion
/*
* TickMark support
*
* - double TickFrequency
* - bool IsSnapToTickEnabled
* - Enum TickPlacement
* - DoubleCollection Ticks
*/
#region TickMark support
///
/// The DependencyProperty for the IsSnapToTickEnabled property.
///
public static readonly DependencyProperty IsSnapToTickEnabledProperty
= DependencyProperty.Register("IsSnapToTickEnabled", typeof(bool), typeof(Slider),
new FrameworkPropertyMetadata(false));
///
/// When 'true', Slider will automatically move the Thumb (and/or change current value) to the closest TickMark.
///
[Bindable(true), Category("Behavior")]
public bool IsSnapToTickEnabled
{
get
{
return (bool)GetValue(IsSnapToTickEnabledProperty);
}
set
{
SetValue(IsSnapToTickEnabledProperty, value);
}
}
///
/// The DependencyProperty for the TickPlacement property.
///
public static readonly DependencyProperty TickPlacementProperty
= DependencyProperty.Register("TickPlacement", typeof(Primitives.TickPlacement), typeof(Slider),
new FrameworkPropertyMetadata(Primitives.TickPlacement.None),
new ValidateValueCallback(IsValidTickPlacement));
///
/// Slider uses this value to determine where to show the Ticks.
/// When Ticks is not 'null', Slider will ignore 'TickFrequency', and draw only TickMarks
/// that specified in Ticks collection.
///
[Bindable(true), Category("Appearance")]
public Primitives.TickPlacement TickPlacement
{
get
{
return (Primitives.TickPlacement)GetValue(TickPlacementProperty);
}
set
{
SetValue(TickPlacementProperty, value);
}
}
private static bool IsValidTickPlacement(object o)
{
TickPlacement value = (TickPlacement)o;
return value == TickPlacement.None ||
value == TickPlacement.TopLeft ||
value == TickPlacement.BottomRight ||
value == TickPlacement.Both;
}
///
/// The DependencyProperty for the TickFrequency property.
/// Default Value is 1.0
///
public static readonly DependencyProperty TickFrequencyProperty
= DependencyProperty.Register("TickFrequency", typeof(double), typeof(Slider),
new FrameworkPropertyMetadata(1.0),
new ValidateValueCallback(IsValidDoubleValue));
///
/// Slider uses this value to determine where to show the Ticks.
/// When Ticks is not 'null', Slider will ignore 'TickFrequency', and draw only TickMarks
/// that specified in Ticks collection.
///
[Bindable(true), Category("Appearance")]
public double TickFrequency
{
get
{
return (double)GetValue(TickFrequencyProperty);
}
set
{
SetValue(TickFrequencyProperty, value);
}
}
//
///
/// The DependencyProperty for the Ticks property.
///
public static readonly DependencyProperty TicksProperty
= DependencyProperty.Register("Ticks", typeof(DoubleCollection), typeof(Slider),
new FrameworkPropertyMetadata(new FreezableDefaultValueFactory(DoubleCollection.Empty)));
///
/// Slider uses this value to determine where to show the Ticks.
/// When Ticks is not 'null', Slider will ignore 'TickFrequency', and draw only TickMarks
/// that specified in Ticks collection.
///
[Bindable(true), Category("Appearance")]
public DoubleCollection Ticks
{
get
{
return (DoubleCollection)GetValue(TicksProperty);
}
set
{
SetValue(TicksProperty, value);
}
}
#endregion TickMark support
/*
* Selection support
*
* - bool IsSelectionRangeEnabled
* - double SelectionStart
* - double SelectionEnd
*/
#region Selection supports
///
/// The DependencyProperty for the IsSelectionRangeEnabled property.
///
public static readonly DependencyProperty IsSelectionRangeEnabledProperty
= DependencyProperty.Register("IsSelectionRangeEnabled", typeof(bool), typeof(Slider),
new FrameworkPropertyMetadata(false));
///
/// Enable or disable selection support on Slider
///
[Bindable(true), Category("Appearance")]
public bool IsSelectionRangeEnabled
{
get
{
return (bool)GetValue(IsSelectionRangeEnabledProperty);
}
set
{
SetValue(IsSelectionRangeEnabledProperty, value);
}
}
///
/// The DependencyProperty for the SelectionStart property.
///
public static readonly DependencyProperty SelectionStartProperty
= DependencyProperty.Register("SelectionStart", typeof(double), typeof(Slider),
new FrameworkPropertyMetadata(0.0d,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
new PropertyChangedCallback(OnSelectionStartChanged),
new CoerceValueCallback(CoerceSelectionStart)),
new ValidateValueCallback(IsValidDoubleValue));
///
/// Get or set starting value of selection.
///
[Bindable(true), Category("Appearance")]
public double SelectionStart
{
get { return (double) GetValue(SelectionStartProperty); }
set { SetValue(SelectionStartProperty, value); }
}
private static void OnSelectionStartChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Slider ctrl = (Slider)d;
double oldValue = (double)e.OldValue;
double newValue = (double)e.NewValue;
ctrl.CoerceValue(SelectionEndProperty);
ctrl.UpdateSelectionRangeElementPositionAndSize();
}
private static object CoerceSelectionStart(DependencyObject d, object value)
{
Slider slider = (Slider)d;
double selection = (double)value;
double min = slider.Minimum;
double max = slider.Maximum;
if (selection < min)
{
return min;
}
if (selection > max)
{
return max;
}
return value;
}
///
/// The DependencyProperty for the SelectionEnd property.
///
public static readonly DependencyProperty SelectionEndProperty
= DependencyProperty.Register("SelectionEnd", typeof(double), typeof(Slider),
new FrameworkPropertyMetadata(0.0d,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
new PropertyChangedCallback(OnSelectionEndChanged),
new CoerceValueCallback(CoerceSelectionEnd)),
new ValidateValueCallback(IsValidDoubleValue));
///
/// Get or set starting value of selection.
///
[Bindable(true), Category("Appearance")]
public double SelectionEnd
{
get { return (double) GetValue(SelectionEndProperty); }
set { SetValue(SelectionEndProperty, value); }
}
private static void OnSelectionEndChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Slider ctrl = (Slider)d;
ctrl.UpdateSelectionRangeElementPositionAndSize();
}
private static object CoerceSelectionEnd(DependencyObject d, object value)
{
Slider slider = (Slider)d;
double selection = (double)value;
double min = slider.SelectionStart;
double max = slider.Maximum;
if (selection < min)
{
return min;
}
if (selection > max)
{
return max;
}
return value;
}
///
/// Called when the value of SelectionEnd is required by the property system.
///
/// The object on which the property was queried.
/// The value of the SelectionEnd property on "d."
private static object OnGetSelectionEnd(DependencyObject d)
{
return ((Slider)d).SelectionEnd;
}
///
/// This method is invoked when the Minimum property changes.
///
/// The old value of the Minimum property.
/// The new value of the Minimum property.
protected override void OnMinimumChanged(double oldMinimum, double newMinimum)
{
CoerceValue(SelectionStartProperty);
}
///
/// This method is invoked when the Maximum property changes.
///
/// The old value of the Maximum property.
/// The new value of the Maximum property.
protected override void OnMaximumChanged(double oldMaximum, double newMaximum)
{
CoerceValue(SelectionStartProperty);
CoerceValue(SelectionEndProperty);
}
#endregion Selection supports
/*
* Move-To-Point support
*
* Property
* - bool IsMoveToPointEnabled
*
* Event Handlers
* - OnPreviewMouseLeftButtonDown
* - double SelectionEnd
*/
#region Move-To-Point support
///
/// The DependencyProperty for the IsMoveToPointEnabled property.
///
public static readonly DependencyProperty IsMoveToPointEnabledProperty
= DependencyProperty.Register("IsMoveToPointEnabled", typeof(bool), typeof(Slider),
new FrameworkPropertyMetadata(false));
///
/// Enable or disable Move-To-Point support on Slider.
/// Move-To-Point feature, enables Slider to immediately move the Thumb directly to the location where user
/// clicked the Mouse.
///
[Bindable(true), Category("Behavior")]
public bool IsMoveToPointEnabled
{
get
{
return (bool)GetValue(IsMoveToPointEnabledProperty);
}
set
{
SetValue(IsMoveToPointEnabledProperty, value);
}
}
///
/// When IsMoveToPointEneabled is 'true', Slider needs to preview MouseLeftButtonDown event, in order prevent its RepeatButtons
/// from handle Left-Click.
///
///
protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
{
if (IsMoveToPointEnabled && Track != null && Track.Thumb != null && !Track.Thumb.IsMouseOver)
{
// Move Thumb to the Mouse location
Point pt = e.MouseDevice.GetPosition(Track);
double newValue = Track.ValueFromPoint(pt);
if (System.Windows.Shapes.Shape.IsDoubleFinite(newValue))
{
UpdateValue(newValue);
}
e.Handled = true;
}
base.OnPreviewMouseLeftButtonDown(e);
}
#endregion Move-To-Point support
#endregion // Properties
#region Event Handlers
///
/// Listen to Thumb DragStarted event.
///
///
///
private static void OnThumbDragStarted(object sender, DragStartedEventArgs e)
{
Slider slider = sender as Slider;
slider.OnThumbDragStarted(e);
}
///
/// Listen to Thumb DragDelta event.
///
///
///
private static void OnThumbDragDelta(object sender, DragDeltaEventArgs e)
{
Slider slider = sender as Slider;
slider.OnThumbDragDelta(e);
}
///
/// Listen to Thumb DragCompleted event.
///
///
///
private static void OnThumbDragCompleted(object sender, DragCompletedEventArgs e)
{
Slider slider = sender as Slider;
slider.OnThumbDragCompleted(e);
}
///
/// Called when user start dragging the Thumb.
/// This function can be override to customize the way Slider handles Thumb movement.
///
///
protected virtual void OnThumbDragStarted(DragStartedEventArgs e)
{
// Show AutoToolTip if needed.
Thumb thumb = e.OriginalSource as Thumb;
if ((thumb == null) || (this.AutoToolTipPlacement == Primitives.AutoToolTipPlacement.None))
{
return;
}
// Save original tooltip
_thumbOriginalToolTip = thumb.ToolTip;
if (_autoToolTip == null)
{
_autoToolTip = new ToolTip();
_autoToolTip.Placement = PlacementMode.Custom;
_autoToolTip.PlacementTarget = thumb;
_autoToolTip.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(this.AutoToolTipCustomPlacementCallback);
}
thumb.ToolTip = _autoToolTip;
_autoToolTip.Content = GetAutoToolTipNumber();
_autoToolTip.IsOpen = true;
((Popup)_autoToolTip.Parent).Reposition();
}
///
/// Called when user dragging the Thumb.
/// This function can be override to customize the way Slider handles Thumb movement.
///
///
protected virtual void OnThumbDragDelta(DragDeltaEventArgs e)
{
Thumb thumb = e.OriginalSource as Thumb;
// Convert to Track's co-ordinate
if (Track != null && thumb == Track.Thumb)
{
double newValue = Value + Track.ValueFromDistance(e.HorizontalChange, e.VerticalChange);
if (System.Windows.Shapes.Shape.IsDoubleFinite(newValue))
{
UpdateValue(newValue);
}
// Show AutoToolTip if needed
if (this.AutoToolTipPlacement != Primitives.AutoToolTipPlacement.None)
{
if (_autoToolTip == null)
{
_autoToolTip = new ToolTip();
}
_autoToolTip.Content = GetAutoToolTipNumber();
if (thumb.ToolTip != _autoToolTip)
{
thumb.ToolTip = _autoToolTip;
}
if (!_autoToolTip.IsOpen)
{
_autoToolTip.IsOpen = true;
}
((Popup)_autoToolTip.Parent).Reposition();
}
}
}
private string GetAutoToolTipNumber()
{
NumberFormatInfo format = (NumberFormatInfo)(NumberFormatInfo.CurrentInfo.Clone());
format.NumberDecimalDigits = this.AutoToolTipPrecision;
return this.Value.ToString("N", format);
}
///
/// Called when user stop dragging the Thumb.
/// This function can be override to customize the way Slider handles Thumb movement.
///
///
protected virtual void OnThumbDragCompleted(DragCompletedEventArgs e)
{
// Show AutoToolTip if needed.
Thumb thumb = e.OriginalSource as Thumb;
if ((thumb == null) || (this.AutoToolTipPlacement == Primitives.AutoToolTipPlacement.None))
{
return;
}
if (_autoToolTip != null)
{
_autoToolTip.IsOpen = false;
}
thumb.ToolTip = _thumbOriginalToolTip;
}
private CustomPopupPlacement[] AutoToolTipCustomPlacementCallback(Size popupSize, Size targetSize, Point offset)
{
switch (this.AutoToolTipPlacement)
{
case Primitives.AutoToolTipPlacement.TopLeft:
if (Orientation == Orientation.Horizontal)
{
// Place popup at top of thumb
return new CustomPopupPlacement[]{new CustomPopupPlacement(
new Point((targetSize.Width - popupSize.Width) * 0.5, -popupSize.Height),
PopupPrimaryAxis.Horizontal)
};
}
else
{
// Place popup at left of thumb
return new CustomPopupPlacement[] {
new CustomPopupPlacement(
new Point(-popupSize.Width, (targetSize.Height - popupSize.Height) * 0.5),
PopupPrimaryAxis.Vertical)
};
}
case Primitives.AutoToolTipPlacement.BottomRight:
if (Orientation == Orientation.Horizontal)
{
// Place popup at bottom of thumb
return new CustomPopupPlacement[] {
new CustomPopupPlacement(
new Point((targetSize.Width - popupSize.Width) * 0.5, targetSize.Height) ,
PopupPrimaryAxis.Horizontal)
};
}
else
{
// Place popup at right of thumb
return new CustomPopupPlacement[] {
new CustomPopupPlacement(
new Point(targetSize.Width, (targetSize.Height - popupSize.Height) * 0.5),
PopupPrimaryAxis.Vertical)
};
}
default:
return new CustomPopupPlacement[]{};
}
}
///
/// Resize and resposition the SelectionRangeElement.
///
private void UpdateSelectionRangeElementPositionAndSize()
{
Size trackSize = new Size(0d, 0d);
Size thumbSize = new Size(0d, 0d);
if (Track == null || DoubleUtil.LessThan(SelectionEnd,SelectionStart))
{
return;
}
trackSize = Track.RenderSize;
thumbSize = (Track.Thumb != null) ? Track.Thumb.RenderSize : new Size(0d, 0d);
double range = Maximum - Minimum;
double valueToSize;
FrameworkElement rangeElement = this.SelectionRangeElement as FrameworkElement;
if (rangeElement == null)
{
return;
}
if (Orientation == Orientation.Horizontal)
{
// Calculate part size for HorizontalSlider
if (DoubleUtil.AreClose(range, 0d) || (DoubleUtil.AreClose(trackSize.Width, thumbSize.Width)))
{
valueToSize = 0d;
}
else
{
valueToSize = Math.Max(0.0, (trackSize.Width - thumbSize.Width) / range);
}
rangeElement.Width = ((SelectionEnd - SelectionStart) * valueToSize);
if (IsDirectionReversed)
{
Canvas.SetLeft(rangeElement, (thumbSize.Width * 0.5) + Math.Max(Maximum - SelectionEnd, 0) * valueToSize);
}
else
{
Canvas.SetLeft(rangeElement, (thumbSize.Width * 0.5) + Math.Max(SelectionStart - Minimum, 0) * valueToSize);
}
}
else
{
// Calculate part size for VerticalSlider
if (DoubleUtil.AreClose(range, 0d) || (DoubleUtil.AreClose(trackSize.Height, thumbSize.Height)))
{
valueToSize = 0d;
}
else
{
valueToSize = Math.Max(0.0, (trackSize.Height - thumbSize.Height) / range);
}
rangeElement.Height = ((SelectionEnd - SelectionStart) * valueToSize);
if (IsDirectionReversed)
{
Canvas.SetTop(rangeElement, (thumbSize.Height * 0.5) + Math.Max(SelectionStart - Minimum, 0) * valueToSize);
}
else
{
Canvas.SetTop(rangeElement, (thumbSize.Height * 0.5) + Math.Max(Maximum - SelectionEnd,0) * valueToSize);
}
}
}
///
/// Gets or sets reference to Slider's Track element.
///
internal Track Track
{
get
{
return _track;
}
set
{
_track = value;
}
}
///
/// Gets or sets reference to Slider's SelectionRange element.
///
internal FrameworkElement SelectionRangeElement
{
get
{
return _selectionRangeElement;
}
set
{
_selectionRangeElement = value;
}
}
///
/// Snap the input 'value' to the closest tick.
/// If input value is exactly in the middle of 2 surrounding ticks, it will be snapped to the tick that has greater value.
///
/// Value that want to snap to closest Tick.
/// Snapped value if IsSnapToTickEnabled is 'true'. Otherwise, returns un-snaped value.
private double SnapToTick(double value)
{
if (IsSnapToTickEnabled)
{
double previous = Minimum;
double next = Maximum;
// This property is rarely set so let's try to avoid the GetValue
// caching of the mutable default value
DoubleCollection ticks = null;
bool hasModifiers;
if (GetValueSource(TicksProperty, null, out hasModifiers)
!= BaseValueSourceInternal.Default || hasModifiers)
{
ticks = Ticks;
}
// If ticks collection is available, use it.
// Note that ticks may be unsorted.
if ((ticks != null) && (ticks.Count > 0))
{
for (int i = 0; i < ticks.Count; i++)
{
double tick = ticks[i];
if (DoubleUtil.AreClose(tick, value))
{
return value;
}
if (DoubleUtil.LessThan(tick, value) && DoubleUtil.GreaterThan(tick, previous))
{
previous = tick;
}
else if (DoubleUtil.GreaterThan(tick ,value) && DoubleUtil.LessThan(tick, next))
{
next = tick;
}
}
}
else if (DoubleUtil.GreaterThan(TickFrequency, 0.0))
{
previous = Minimum + (Math.Round(((value - Minimum) / TickFrequency)) * TickFrequency);
next = Math.Min(Maximum, previous + TickFrequency);
}
// Choose the closest value between previous and next. If tie, snap to 'next'.
value = DoubleUtil.GreaterThanOrClose(value, (previous + next) * 0.5) ? next : previous;
}
return value;
}
// Sets Value = SnapToTick(value+direction), unless the result of SnapToTick is Value,
// then it searches for the next tick greater(if direction is positive) than value
// and sets Value to that tick
private void MoveToNextTick(double direction)
{
if (direction != 0.0)
{
double value = this.Value;
// Find the next value by snapping
double next = SnapToTick(Math.Max(this.Minimum, Math.Min(this.Maximum, value + direction)));
bool greaterThan = direction > 0; //search for the next tick greater than value?
// If the snapping brought us back to value, find the next tick point
if (next == value
&& !( greaterThan && value == Maximum) // Stop if searching up if already at Max
&& !(!greaterThan && value == Minimum)) // Stop if searching down if already at Min
{
// This property is rarely set so let's try to avoid the GetValue
// caching of the mutable default value
DoubleCollection ticks = null;
bool hasModifiers;
if (GetValueSource(TicksProperty, null, out hasModifiers)
!= BaseValueSourceInternal.Default || hasModifiers)
{
ticks = Ticks;
}
// If ticks collection is available, use it.
// Note that ticks may be unsorted.
if ((ticks != null) && (ticks.Count > 0))
{
for (int i = 0; i < ticks.Count; i++)
{
double tick = ticks[i];
// Find the smallest tick greater than value or the largest tick less than value
if ((greaterThan && DoubleUtil.GreaterThan(tick, value) && (DoubleUtil.LessThan(tick, next) || next == value))
||(!greaterThan && DoubleUtil.LessThan(tick, value) && (DoubleUtil.GreaterThan(tick, next) || next == value)))
{
next = tick;
}
}
}
else if (DoubleUtil.GreaterThan(TickFrequency, 0.0))
{
// Find the current tick we are at
double tickNumber = Math.Round((value - Minimum) / TickFrequency);
if (greaterThan)
tickNumber += 1.0;
else
tickNumber -= 1.0;
next = Minimum + tickNumber * TickFrequency;
}
}
// Update if we've found a better value
if (next != value)
{
this.Value = next;
}
}
}
#endregion Event Handlers
#region Override Functions
///
/// Creates AutomationPeer ( )
///
protected override AutomationPeer OnCreateAutomationPeer()
{
return new SliderAutomationPeer(this);
}
///
/// This is a class handler for MouseLeftButtonDown event.
/// The purpose of this handle is to move input focus to Slider when user pressed
/// mouse left button on any part of slider that is not focusable.
///
///
///
private static void _OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if(e.ChangedButton != MouseButton.Left) return;
Slider slider = (Slider)sender;
// When someone click on the Slider's part, and it's not focusable
// Slider need to take the focus in order to process keyboard correctly
if (!slider.IsKeyboardFocusWithin)
{
e.Handled = slider.Focus() || e.Handled;
}
}
///
/// Perform arrangement of slider's children
///
///
protected override Size ArrangeOverride(Size finalSize)
{
Size size = base.ArrangeOverride(finalSize);
UpdateSelectionRangeElementPositionAndSize();
return size;
}
///
/// Update SelectionRange Length.
///
///
///
protected override void OnValueChanged(double oldValue, double newValue)
{
base.OnValueChanged(oldValue, newValue);
UpdateSelectionRangeElementPositionAndSize();
}
///
/// Slider locates the SelectionRangeElement when its visual tree is created
///
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
SelectionRangeElement = GetTemplateChild(SelectionRangeElementName) as FrameworkElement;
Track = GetTemplateChild(TrackName) as Track;
if (_autoToolTip != null)
{
_autoToolTip.PlacementTarget = Track != null ? Track.Thumb : null;
}
}
#endregion Override Functions
#region Virtual Functions
///
/// Call when Slider.IncreaseLarge command is invoked.
///
protected virtual void OnIncreaseLarge()
{
MoveToNextTick(this.LargeChange);
}
///
/// Call when Slider.DecreaseLarge command is invoked.
///
protected virtual void OnDecreaseLarge()
{
MoveToNextTick(-this.LargeChange);
}
///
/// Call when Slider.IncreaseSmall command is invoked.
///
protected virtual void OnIncreaseSmall()
{
MoveToNextTick(this.SmallChange);
}
///
/// Call when Slider.DecreaseSmall command is invoked.
///
protected virtual void OnDecreaseSmall()
{
MoveToNextTick(-this.SmallChange);
}
///
/// Call when Slider.MaximizeValue command is invoked.
///
protected virtual void OnMaximizeValue()
{
this.Value = this.Maximum;
}
///
/// Call when Slider.MinimizeValue command is invoked.
///
protected virtual void OnMinimizeValue()
{
this.Value = this.Minimum;
}
#endregion Virtual Functions
#region Helper Functions
///
/// Helper function for value update.
/// This function will also snap the value to tick, if IsSnapToTickEnabled is true.
///
///
private void UpdateValue(double value)
{
Double snappedValue = SnapToTick(value);
if (snappedValue != Value)
{
Value = Math.Max(this.Minimum, Math.Min(this.Maximum, snappedValue));
}
}
///
/// Validate input value in Slider (LargeChange, SmallChange, SelectionStart, SelectionEnd, and TickFrequency).
///
///
/// Returns False if value is NaN or NegativeInfinity or PositiveInfinity. Otherwise, returns True.
private static bool IsValidDoubleValue(object value)
{
double d = (double)value;
return !(DoubleUtil.IsNaN(d) || double.IsInfinity(d));
}
#endregion Helper Functions
#region Private Fields
private const string TrackName = "PART_Track";
private const string SelectionRangeElementName = "PART_SelectionRange";
// Slider required parts
private FrameworkElement _selectionRangeElement;
private Track _track;
private ToolTip _autoToolTip = null;
private object _thumbOriginalToolTip = null;
#endregion Private Fields
#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
}
}
// 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.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Collections;
using System.Windows.Threading;
using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using MS.Win32;
using MS.Internal;
using MS.Internal.Commands;
// For typeconverter
using System.ComponentModel.Design.Serialization;
using System.Reflection;
namespace System.Windows.Controls
{
///
/// Slider control lets the user select from a range of values by moving a slider.
/// Slider is used to enable to user to gradually modify a value (range selection).
/// Slider is an easy and natural interface for users, because it provides good visual feedback.
///
///
[Localizability(LocalizationCategory.Ignore)]
[DefaultEvent("ValueChanged"), DefaultProperty("Value")]
[TemplatePart(Name = "PART_Track", Type = typeof(Track))]
[TemplatePart(Name = "PART_SelectionRange", Type = typeof(FrameworkElement))]
public class Slider : RangeBase
{
#region Constructors
///
/// Instantiates a new instance of a Slider with out Dispatcher.
///
///
public Slider() : base()
{
}
///
/// This is the static constructor for the Slider class. It
/// simply registers the appropriate class handlers for the input
/// devices, and defines a default style sheet.
///
static Slider()
{
// Initialize CommandCollection & CommandLink(s)
InitializeCommands();
// Register all PropertyTypeMetadata
MinimumProperty.OverrideMetadata(typeof(Slider), new FrameworkPropertyMetadata(0.0d, FrameworkPropertyMetadataOptions.AffectsMeasure));
MaximumProperty.OverrideMetadata(typeof(Slider), new FrameworkPropertyMetadata(10.0d, FrameworkPropertyMetadataOptions.AffectsMeasure));
ValueProperty.OverrideMetadata(typeof(Slider), new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsMeasure));
// Register Event Handler for the Thumb
EventManager.RegisterClassHandler(typeof(Slider), Thumb.DragStartedEvent, new DragStartedEventHandler(Slider.OnThumbDragStarted));
EventManager.RegisterClassHandler(typeof(Slider), Thumb.DragDeltaEvent, new DragDeltaEventHandler(Slider.OnThumbDragDelta));
EventManager.RegisterClassHandler(typeof(Slider), Thumb.DragCompletedEvent, new DragCompletedEventHandler(Slider.OnThumbDragCompleted));
// Listen to MouseLeftButtonDown event to determine if slide should move focus to itself
EventManager.RegisterClassHandler(typeof(Slider), Mouse.MouseDownEvent, new MouseButtonEventHandler(Slider._OnMouseLeftButtonDown),true);
DefaultStyleKeyProperty.OverrideMetadata(typeof(Slider), new FrameworkPropertyMetadata(typeof(Slider)));
_dType = DependencyObjectType.FromSystemTypeInternal(typeof(Slider));
}
#endregion Constructors
#region Commands
private static RoutedCommand _increaseLargeCommand = null;
private static RoutedCommand _increaseSmallCommand = null;
private static RoutedCommand _decreaseLargeCommand = null;
private static RoutedCommand _decreaseSmallCommand = null;
private static RoutedCommand _minimizeValueCommand = null;
private static RoutedCommand _maximizeValueCommand = null;
///
/// Increase Slider value
///
public static RoutedCommand IncreaseLarge
{
get { return _increaseLargeCommand; }
}
///
/// Decrease Slider value
///
public static RoutedCommand DecreaseLarge
{
get { return _decreaseLargeCommand; }
}
///
/// Increase Slider value
///
public static RoutedCommand IncreaseSmall
{
get { return _increaseSmallCommand; }
}
///
/// Decrease Slider value
///
public static RoutedCommand DecreaseSmall
{
get { return _decreaseSmallCommand; }
}
///
/// Set Slider value to mininum
///
public static RoutedCommand MinimizeValue
{
get { return _minimizeValueCommand; }
}
///
/// Set Slider value to maximum
///
public static RoutedCommand MaximizeValue
{
get { return _maximizeValueCommand; }
}
static void InitializeCommands()
{
_increaseLargeCommand = new RoutedCommand("IncreaseLarge", typeof(Slider));
_decreaseLargeCommand = new RoutedCommand("DecreaseLarge", typeof(Slider));
_increaseSmallCommand = new RoutedCommand("IncreaseSmall", typeof(Slider));
_decreaseSmallCommand = new RoutedCommand("DecreaseSmall", typeof(Slider));
_minimizeValueCommand = new RoutedCommand("MinimizeValue", typeof(Slider));
_maximizeValueCommand = new RoutedCommand("MaximizeValue", typeof(Slider));
CommandHelpers.RegisterCommandHandler(typeof(Slider), _increaseLargeCommand, new ExecutedRoutedEventHandler(OnIncreaseLargeCommand),
new SliderGesture(Key.PageUp, Key.PageDown, false));
CommandHelpers.RegisterCommandHandler(typeof(Slider), _decreaseLargeCommand, new ExecutedRoutedEventHandler(OnDecreaseLargeCommand),
new SliderGesture(Key.PageDown, Key.PageUp, false));
CommandHelpers.RegisterCommandHandler(typeof(Slider), _increaseSmallCommand, new ExecutedRoutedEventHandler(OnIncreaseSmallCommand),
new SliderGesture(Key.Up, Key.Down, false),
new SliderGesture(Key.Right, Key.Left, true));
CommandHelpers.RegisterCommandHandler(typeof(Slider), _decreaseSmallCommand, new ExecutedRoutedEventHandler(OnDecreaseSmallCommand),
new SliderGesture(Key.Down, Key.Up, false),
new SliderGesture(Key.Left, Key.Right, true));
CommandHelpers.RegisterCommandHandler(typeof(Slider), _minimizeValueCommand, new ExecutedRoutedEventHandler(OnMinimizeValueCommand),
Key.Home);
CommandHelpers.RegisterCommandHandler(typeof(Slider), _maximizeValueCommand, new ExecutedRoutedEventHandler(OnMaximizeValueCommand),
Key.End);
}
private class SliderGesture : InputGesture
{
public SliderGesture(Key normal, Key inverted, bool forHorizontal)
{
_normal = normal;
_inverted = inverted;
_forHorizontal = forHorizontal;
}
///
/// Sees if the InputGesture matches the input associated with the inputEventArgs
///
public override bool Matches(object targetElement, InputEventArgs inputEventArgs)
{
KeyEventArgs keyEventArgs = inputEventArgs as KeyEventArgs;
Slider slider = targetElement as Slider;
if (keyEventArgs != null && slider != null && Keyboard.Modifiers == ModifierKeys.None)
{
if((int)_normal == (int)keyEventArgs.RealKey)
{
return !IsInverted(slider);
}
if ((int)_inverted == (int)keyEventArgs.RealKey)
{
return IsInverted(slider);
}
}
return false;
}
private bool IsInverted(Slider slider)
{
if (_forHorizontal)
{
return slider.IsDirectionReversed != (slider.FlowDirection == FlowDirection.RightToLeft);
}
else
{
return slider.IsDirectionReversed;
}
}
private Key _normal, _inverted;
private bool _forHorizontal;
}
private static void OnIncreaseSmallCommand(object sender, ExecutedRoutedEventArgs e)
{
Slider slider = sender as Slider;
if (slider != null)
{
slider.OnIncreaseSmall();
}
}
private static void OnDecreaseSmallCommand(object sender, ExecutedRoutedEventArgs e)
{
Slider slider = sender as Slider;
if (slider != null)
{
slider.OnDecreaseSmall();
}
}
private static void OnMaximizeValueCommand(object sender, ExecutedRoutedEventArgs e)
{
Slider slider = sender as Slider;
if (slider != null)
{
slider.OnMaximizeValue();
}
}
private static void OnMinimizeValueCommand(object sender, ExecutedRoutedEventArgs e)
{
Slider slider = sender as Slider;
if (slider != null)
{
slider.OnMinimizeValue();
}
}
private static void OnIncreaseLargeCommand(object sender, ExecutedRoutedEventArgs e)
{
Slider slider = sender as Slider;
if (slider != null)
{
slider.OnIncreaseLarge();
}
}
private static void OnDecreaseLargeCommand(object sender, ExecutedRoutedEventArgs e)
{
Slider slider = sender as Slider;
if (slider != null)
{
slider.OnDecreaseLarge();
}
}
#endregion Commands
#region Properties
#region Orientation Property
///
/// DependencyProperty for property.
///
public static readonly DependencyProperty OrientationProperty =
DependencyProperty.Register("Orientation", typeof(Orientation), typeof(Slider),
new FrameworkPropertyMetadata(Orientation.Horizontal),
new ValidateValueCallback(ScrollBar.IsValidOrientation));
///
/// Get/Set Orientation property
///
public Orientation Orientation
{
get { return (Orientation)GetValue(OrientationProperty); }
set { SetValue(OrientationProperty, value); }
}
#endregion
#region IsDirectionReversed Property
///
/// Slider ThumbProportion property
///
public static readonly DependencyProperty IsDirectionReversedProperty
= DependencyProperty.Register("IsDirectionReversed", typeof(bool), typeof(Slider),
new FrameworkPropertyMetadata(false));
///
/// Get/Set IsDirectionReversed property
///
[Bindable(true), Category("Appearance")]
public bool IsDirectionReversed
{
get
{
return (bool)GetValue(IsDirectionReversedProperty);
}
set
{
SetValue(IsDirectionReversedProperty, value);
}
}
#endregion
#region Delay Property
///
/// The Property for the Delay property.
///
public static readonly DependencyProperty DelayProperty = RepeatButton.DelayProperty.AddOwner(typeof(Slider), new FrameworkPropertyMetadata(RepeatButton.GetKeyboardDelay()));
///
/// Specifies the amount of time, in milliseconds, to wait before repeating begins.
/// Must be non-negative.
///
[Bindable(true), Category("Behavior")]
public int Delay
{
get
{
return (int)GetValue(DelayProperty);
}
set
{
SetValue(DelayProperty, value);
}
}
#endregion Delay Property
#region Interval Property
///
/// The Property for the Interval property.
///
public static readonly DependencyProperty IntervalProperty = RepeatButton.IntervalProperty.AddOwner(typeof(Slider), new FrameworkPropertyMetadata(RepeatButton.GetKeyboardSpeed()));
///
/// Specifies the amount of time, in milliseconds, between repeats once repeating starts.
/// Must be non-negative
///
[Bindable(true), Category("Behavior")]
public int Interval
{
get
{
return (int)GetValue(IntervalProperty);
}
set
{
SetValue(IntervalProperty, value);
}
}
#endregion Interval Property
#region AutoToolTipPlacement Property
///
/// The DependencyProperty for the AutoToolTipPlacement property.
///
public static readonly DependencyProperty AutoToolTipPlacementProperty
= DependencyProperty.Register("AutoToolTipPlacement", typeof(AutoToolTipPlacement), typeof(Slider),
new FrameworkPropertyMetadata(Primitives.AutoToolTipPlacement.None),
new ValidateValueCallback(IsValidAutoToolTipPlacement));
///
/// AutoToolTipPlacement property specifies the placement of the AutoToolTip
///
[Bindable(true), Category("Behavior")]
public Primitives.AutoToolTipPlacement AutoToolTipPlacement
{
get
{
return (Primitives.AutoToolTipPlacement)GetValue(AutoToolTipPlacementProperty);
}
set
{
SetValue(AutoToolTipPlacementProperty, value);
}
}
private static bool IsValidAutoToolTipPlacement(object o)
{
AutoToolTipPlacement placement = (AutoToolTipPlacement)o;
return placement == AutoToolTipPlacement.None ||
placement == AutoToolTipPlacement.TopLeft ||
placement == AutoToolTipPlacement.BottomRight;
}
#endregion
#region AutoToolTipPrecision Property
///
/// The DependencyProperty for the AutoToolTipPrecision property.
/// Flags: None
/// Default Value: 0
///
public static readonly DependencyProperty AutoToolTipPrecisionProperty
= DependencyProperty.Register("AutoToolTipPrecision", typeof(int), typeof(Slider),
new FrameworkPropertyMetadata(0), new ValidateValueCallback(IsValidAutoToolTipPrecision));
///
/// Get or set number of decimal digits of Slider's Value shown in AutoToolTip
///
[Bindable(true), Category("Appearance")]
public int AutoToolTipPrecision
{
get
{
return (int)GetValue(AutoToolTipPrecisionProperty);
}
set
{
SetValue(AutoToolTipPrecisionProperty, value);
}
}
///
/// Validates AutoToolTipPrecision value
///
///
///
private static bool IsValidAutoToolTipPrecision(object o)
{
return (((int)o) >= 0);
}
#endregion
/*
* TickMark support
*
* - double TickFrequency
* - bool IsSnapToTickEnabled
* - Enum TickPlacement
* - DoubleCollection Ticks
*/
#region TickMark support
///
/// The DependencyProperty for the IsSnapToTickEnabled property.
///
public static readonly DependencyProperty IsSnapToTickEnabledProperty
= DependencyProperty.Register("IsSnapToTickEnabled", typeof(bool), typeof(Slider),
new FrameworkPropertyMetadata(false));
///
/// When 'true', Slider will automatically move the Thumb (and/or change current value) to the closest TickMark.
///
[Bindable(true), Category("Behavior")]
public bool IsSnapToTickEnabled
{
get
{
return (bool)GetValue(IsSnapToTickEnabledProperty);
}
set
{
SetValue(IsSnapToTickEnabledProperty, value);
}
}
///
/// The DependencyProperty for the TickPlacement property.
///
public static readonly DependencyProperty TickPlacementProperty
= DependencyProperty.Register("TickPlacement", typeof(Primitives.TickPlacement), typeof(Slider),
new FrameworkPropertyMetadata(Primitives.TickPlacement.None),
new ValidateValueCallback(IsValidTickPlacement));
///
/// Slider uses this value to determine where to show the Ticks.
/// When Ticks is not 'null', Slider will ignore 'TickFrequency', and draw only TickMarks
/// that specified in Ticks collection.
///
[Bindable(true), Category("Appearance")]
public Primitives.TickPlacement TickPlacement
{
get
{
return (Primitives.TickPlacement)GetValue(TickPlacementProperty);
}
set
{
SetValue(TickPlacementProperty, value);
}
}
private static bool IsValidTickPlacement(object o)
{
TickPlacement value = (TickPlacement)o;
return value == TickPlacement.None ||
value == TickPlacement.TopLeft ||
value == TickPlacement.BottomRight ||
value == TickPlacement.Both;
}
///
/// The DependencyProperty for the TickFrequency property.
/// Default Value is 1.0
///
public static readonly DependencyProperty TickFrequencyProperty
= DependencyProperty.Register("TickFrequency", typeof(double), typeof(Slider),
new FrameworkPropertyMetadata(1.0),
new ValidateValueCallback(IsValidDoubleValue));
///
/// Slider uses this value to determine where to show the Ticks.
/// When Ticks is not 'null', Slider will ignore 'TickFrequency', and draw only TickMarks
/// that specified in Ticks collection.
///
[Bindable(true), Category("Appearance")]
public double TickFrequency
{
get
{
return (double)GetValue(TickFrequencyProperty);
}
set
{
SetValue(TickFrequencyProperty, value);
}
}
//
///
/// The DependencyProperty for the Ticks property.
///
public static readonly DependencyProperty TicksProperty
= DependencyProperty.Register("Ticks", typeof(DoubleCollection), typeof(Slider),
new FrameworkPropertyMetadata(new FreezableDefaultValueFactory(DoubleCollection.Empty)));
///
/// Slider uses this value to determine where to show the Ticks.
/// When Ticks is not 'null', Slider will ignore 'TickFrequency', and draw only TickMarks
/// that specified in Ticks collection.
///
[Bindable(true), Category("Appearance")]
public DoubleCollection Ticks
{
get
{
return (DoubleCollection)GetValue(TicksProperty);
}
set
{
SetValue(TicksProperty, value);
}
}
#endregion TickMark support
/*
* Selection support
*
* - bool IsSelectionRangeEnabled
* - double SelectionStart
* - double SelectionEnd
*/
#region Selection supports
///
/// The DependencyProperty for the IsSelectionRangeEnabled property.
///
public static readonly DependencyProperty IsSelectionRangeEnabledProperty
= DependencyProperty.Register("IsSelectionRangeEnabled", typeof(bool), typeof(Slider),
new FrameworkPropertyMetadata(false));
///
/// Enable or disable selection support on Slider
///
[Bindable(true), Category("Appearance")]
public bool IsSelectionRangeEnabled
{
get
{
return (bool)GetValue(IsSelectionRangeEnabledProperty);
}
set
{
SetValue(IsSelectionRangeEnabledProperty, value);
}
}
///
/// The DependencyProperty for the SelectionStart property.
///
public static readonly DependencyProperty SelectionStartProperty
= DependencyProperty.Register("SelectionStart", typeof(double), typeof(Slider),
new FrameworkPropertyMetadata(0.0d,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
new PropertyChangedCallback(OnSelectionStartChanged),
new CoerceValueCallback(CoerceSelectionStart)),
new ValidateValueCallback(IsValidDoubleValue));
///
/// Get or set starting value of selection.
///
[Bindable(true), Category("Appearance")]
public double SelectionStart
{
get { return (double) GetValue(SelectionStartProperty); }
set { SetValue(SelectionStartProperty, value); }
}
private static void OnSelectionStartChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Slider ctrl = (Slider)d;
double oldValue = (double)e.OldValue;
double newValue = (double)e.NewValue;
ctrl.CoerceValue(SelectionEndProperty);
ctrl.UpdateSelectionRangeElementPositionAndSize();
}
private static object CoerceSelectionStart(DependencyObject d, object value)
{
Slider slider = (Slider)d;
double selection = (double)value;
double min = slider.Minimum;
double max = slider.Maximum;
if (selection < min)
{
return min;
}
if (selection > max)
{
return max;
}
return value;
}
///
/// The DependencyProperty for the SelectionEnd property.
///
public static readonly DependencyProperty SelectionEndProperty
= DependencyProperty.Register("SelectionEnd", typeof(double), typeof(Slider),
new FrameworkPropertyMetadata(0.0d,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
new PropertyChangedCallback(OnSelectionEndChanged),
new CoerceValueCallback(CoerceSelectionEnd)),
new ValidateValueCallback(IsValidDoubleValue));
///
/// Get or set starting value of selection.
///
[Bindable(true), Category("Appearance")]
public double SelectionEnd
{
get { return (double) GetValue(SelectionEndProperty); }
set { SetValue(SelectionEndProperty, value); }
}
private static void OnSelectionEndChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Slider ctrl = (Slider)d;
ctrl.UpdateSelectionRangeElementPositionAndSize();
}
private static object CoerceSelectionEnd(DependencyObject d, object value)
{
Slider slider = (Slider)d;
double selection = (double)value;
double min = slider.SelectionStart;
double max = slider.Maximum;
if (selection < min)
{
return min;
}
if (selection > max)
{
return max;
}
return value;
}
///
/// Called when the value of SelectionEnd is required by the property system.
///
/// The object on which the property was queried.
/// The value of the SelectionEnd property on "d."
private static object OnGetSelectionEnd(DependencyObject d)
{
return ((Slider)d).SelectionEnd;
}
///
/// This method is invoked when the Minimum property changes.
///
/// The old value of the Minimum property.
/// The new value of the Minimum property.
protected override void OnMinimumChanged(double oldMinimum, double newMinimum)
{
CoerceValue(SelectionStartProperty);
}
///
/// This method is invoked when the Maximum property changes.
///
/// The old value of the Maximum property.
/// The new value of the Maximum property.
protected override void OnMaximumChanged(double oldMaximum, double newMaximum)
{
CoerceValue(SelectionStartProperty);
CoerceValue(SelectionEndProperty);
}
#endregion Selection supports
/*
* Move-To-Point support
*
* Property
* - bool IsMoveToPointEnabled
*
* Event Handlers
* - OnPreviewMouseLeftButtonDown
* - double SelectionEnd
*/
#region Move-To-Point support
///
/// The DependencyProperty for the IsMoveToPointEnabled property.
///
public static readonly DependencyProperty IsMoveToPointEnabledProperty
= DependencyProperty.Register("IsMoveToPointEnabled", typeof(bool), typeof(Slider),
new FrameworkPropertyMetadata(false));
///
/// Enable or disable Move-To-Point support on Slider.
/// Move-To-Point feature, enables Slider to immediately move the Thumb directly to the location where user
/// clicked the Mouse.
///
[Bindable(true), Category("Behavior")]
public bool IsMoveToPointEnabled
{
get
{
return (bool)GetValue(IsMoveToPointEnabledProperty);
}
set
{
SetValue(IsMoveToPointEnabledProperty, value);
}
}
///
/// When IsMoveToPointEneabled is 'true', Slider needs to preview MouseLeftButtonDown event, in order prevent its RepeatButtons
/// from handle Left-Click.
///
///
protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
{
if (IsMoveToPointEnabled && Track != null && Track.Thumb != null && !Track.Thumb.IsMouseOver)
{
// Move Thumb to the Mouse location
Point pt = e.MouseDevice.GetPosition(Track);
double newValue = Track.ValueFromPoint(pt);
if (System.Windows.Shapes.Shape.IsDoubleFinite(newValue))
{
UpdateValue(newValue);
}
e.Handled = true;
}
base.OnPreviewMouseLeftButtonDown(e);
}
#endregion Move-To-Point support
#endregion // Properties
#region Event Handlers
///
/// Listen to Thumb DragStarted event.
///
///
///
private static void OnThumbDragStarted(object sender, DragStartedEventArgs e)
{
Slider slider = sender as Slider;
slider.OnThumbDragStarted(e);
}
///
/// Listen to Thumb DragDelta event.
///
///
///
private static void OnThumbDragDelta(object sender, DragDeltaEventArgs e)
{
Slider slider = sender as Slider;
slider.OnThumbDragDelta(e);
}
///
/// Listen to Thumb DragCompleted event.
///
///
///
private static void OnThumbDragCompleted(object sender, DragCompletedEventArgs e)
{
Slider slider = sender as Slider;
slider.OnThumbDragCompleted(e);
}
///
/// Called when user start dragging the Thumb.
/// This function can be override to customize the way Slider handles Thumb movement.
///
///
protected virtual void OnThumbDragStarted(DragStartedEventArgs e)
{
// Show AutoToolTip if needed.
Thumb thumb = e.OriginalSource as Thumb;
if ((thumb == null) || (this.AutoToolTipPlacement == Primitives.AutoToolTipPlacement.None))
{
return;
}
// Save original tooltip
_thumbOriginalToolTip = thumb.ToolTip;
if (_autoToolTip == null)
{
_autoToolTip = new ToolTip();
_autoToolTip.Placement = PlacementMode.Custom;
_autoToolTip.PlacementTarget = thumb;
_autoToolTip.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(this.AutoToolTipCustomPlacementCallback);
}
thumb.ToolTip = _autoToolTip;
_autoToolTip.Content = GetAutoToolTipNumber();
_autoToolTip.IsOpen = true;
((Popup)_autoToolTip.Parent).Reposition();
}
///
/// Called when user dragging the Thumb.
/// This function can be override to customize the way Slider handles Thumb movement.
///
///
protected virtual void OnThumbDragDelta(DragDeltaEventArgs e)
{
Thumb thumb = e.OriginalSource as Thumb;
// Convert to Track's co-ordinate
if (Track != null && thumb == Track.Thumb)
{
double newValue = Value + Track.ValueFromDistance(e.HorizontalChange, e.VerticalChange);
if (System.Windows.Shapes.Shape.IsDoubleFinite(newValue))
{
UpdateValue(newValue);
}
// Show AutoToolTip if needed
if (this.AutoToolTipPlacement != Primitives.AutoToolTipPlacement.None)
{
if (_autoToolTip == null)
{
_autoToolTip = new ToolTip();
}
_autoToolTip.Content = GetAutoToolTipNumber();
if (thumb.ToolTip != _autoToolTip)
{
thumb.ToolTip = _autoToolTip;
}
if (!_autoToolTip.IsOpen)
{
_autoToolTip.IsOpen = true;
}
((Popup)_autoToolTip.Parent).Reposition();
}
}
}
private string GetAutoToolTipNumber()
{
NumberFormatInfo format = (NumberFormatInfo)(NumberFormatInfo.CurrentInfo.Clone());
format.NumberDecimalDigits = this.AutoToolTipPrecision;
return this.Value.ToString("N", format);
}
///
/// Called when user stop dragging the Thumb.
/// This function can be override to customize the way Slider handles Thumb movement.
///
///
protected virtual void OnThumbDragCompleted(DragCompletedEventArgs e)
{
// Show AutoToolTip if needed.
Thumb thumb = e.OriginalSource as Thumb;
if ((thumb == null) || (this.AutoToolTipPlacement == Primitives.AutoToolTipPlacement.None))
{
return;
}
if (_autoToolTip != null)
{
_autoToolTip.IsOpen = false;
}
thumb.ToolTip = _thumbOriginalToolTip;
}
private CustomPopupPlacement[] AutoToolTipCustomPlacementCallback(Size popupSize, Size targetSize, Point offset)
{
switch (this.AutoToolTipPlacement)
{
case Primitives.AutoToolTipPlacement.TopLeft:
if (Orientation == Orientation.Horizontal)
{
// Place popup at top of thumb
return new CustomPopupPlacement[]{new CustomPopupPlacement(
new Point((targetSize.Width - popupSize.Width) * 0.5, -popupSize.Height),
PopupPrimaryAxis.Horizontal)
};
}
else
{
// Place popup at left of thumb
return new CustomPopupPlacement[] {
new CustomPopupPlacement(
new Point(-popupSize.Width, (targetSize.Height - popupSize.Height) * 0.5),
PopupPrimaryAxis.Vertical)
};
}
case Primitives.AutoToolTipPlacement.BottomRight:
if (Orientation == Orientation.Horizontal)
{
// Place popup at bottom of thumb
return new CustomPopupPlacement[] {
new CustomPopupPlacement(
new Point((targetSize.Width - popupSize.Width) * 0.5, targetSize.Height) ,
PopupPrimaryAxis.Horizontal)
};
}
else
{
// Place popup at right of thumb
return new CustomPopupPlacement[] {
new CustomPopupPlacement(
new Point(targetSize.Width, (targetSize.Height - popupSize.Height) * 0.5),
PopupPrimaryAxis.Vertical)
};
}
default:
return new CustomPopupPlacement[]{};
}
}
///
/// Resize and resposition the SelectionRangeElement.
///
private void UpdateSelectionRangeElementPositionAndSize()
{
Size trackSize = new Size(0d, 0d);
Size thumbSize = new Size(0d, 0d);
if (Track == null || DoubleUtil.LessThan(SelectionEnd,SelectionStart))
{
return;
}
trackSize = Track.RenderSize;
thumbSize = (Track.Thumb != null) ? Track.Thumb.RenderSize : new Size(0d, 0d);
double range = Maximum - Minimum;
double valueToSize;
FrameworkElement rangeElement = this.SelectionRangeElement as FrameworkElement;
if (rangeElement == null)
{
return;
}
if (Orientation == Orientation.Horizontal)
{
// Calculate part size for HorizontalSlider
if (DoubleUtil.AreClose(range, 0d) || (DoubleUtil.AreClose(trackSize.Width, thumbSize.Width)))
{
valueToSize = 0d;
}
else
{
valueToSize = Math.Max(0.0, (trackSize.Width - thumbSize.Width) / range);
}
rangeElement.Width = ((SelectionEnd - SelectionStart) * valueToSize);
if (IsDirectionReversed)
{
Canvas.SetLeft(rangeElement, (thumbSize.Width * 0.5) + Math.Max(Maximum - SelectionEnd, 0) * valueToSize);
}
else
{
Canvas.SetLeft(rangeElement, (thumbSize.Width * 0.5) + Math.Max(SelectionStart - Minimum, 0) * valueToSize);
}
}
else
{
// Calculate part size for VerticalSlider
if (DoubleUtil.AreClose(range, 0d) || (DoubleUtil.AreClose(trackSize.Height, thumbSize.Height)))
{
valueToSize = 0d;
}
else
{
valueToSize = Math.Max(0.0, (trackSize.Height - thumbSize.Height) / range);
}
rangeElement.Height = ((SelectionEnd - SelectionStart) * valueToSize);
if (IsDirectionReversed)
{
Canvas.SetTop(rangeElement, (thumbSize.Height * 0.5) + Math.Max(SelectionStart - Minimum, 0) * valueToSize);
}
else
{
Canvas.SetTop(rangeElement, (thumbSize.Height * 0.5) + Math.Max(Maximum - SelectionEnd,0) * valueToSize);
}
}
}
///
/// Gets or sets reference to Slider's Track element.
///
internal Track Track
{
get
{
return _track;
}
set
{
_track = value;
}
}
///
/// Gets or sets reference to Slider's SelectionRange element.
///
internal FrameworkElement SelectionRangeElement
{
get
{
return _selectionRangeElement;
}
set
{
_selectionRangeElement = value;
}
}
///
/// Snap the input 'value' to the closest tick.
/// If input value is exactly in the middle of 2 surrounding ticks, it will be snapped to the tick that has greater value.
///
/// Value that want to snap to closest Tick.
/// Snapped value if IsSnapToTickEnabled is 'true'. Otherwise, returns un-snaped value.
private double SnapToTick(double value)
{
if (IsSnapToTickEnabled)
{
double previous = Minimum;
double next = Maximum;
// This property is rarely set so let's try to avoid the GetValue
// caching of the mutable default value
DoubleCollection ticks = null;
bool hasModifiers;
if (GetValueSource(TicksProperty, null, out hasModifiers)
!= BaseValueSourceInternal.Default || hasModifiers)
{
ticks = Ticks;
}
// If ticks collection is available, use it.
// Note that ticks may be unsorted.
if ((ticks != null) && (ticks.Count > 0))
{
for (int i = 0; i < ticks.Count; i++)
{
double tick = ticks[i];
if (DoubleUtil.AreClose(tick, value))
{
return value;
}
if (DoubleUtil.LessThan(tick, value) && DoubleUtil.GreaterThan(tick, previous))
{
previous = tick;
}
else if (DoubleUtil.GreaterThan(tick ,value) && DoubleUtil.LessThan(tick, next))
{
next = tick;
}
}
}
else if (DoubleUtil.GreaterThan(TickFrequency, 0.0))
{
previous = Minimum + (Math.Round(((value - Minimum) / TickFrequency)) * TickFrequency);
next = Math.Min(Maximum, previous + TickFrequency);
}
// Choose the closest value between previous and next. If tie, snap to 'next'.
value = DoubleUtil.GreaterThanOrClose(value, (previous + next) * 0.5) ? next : previous;
}
return value;
}
// Sets Value = SnapToTick(value+direction), unless the result of SnapToTick is Value,
// then it searches for the next tick greater(if direction is positive) than value
// and sets Value to that tick
private void MoveToNextTick(double direction)
{
if (direction != 0.0)
{
double value = this.Value;
// Find the next value by snapping
double next = SnapToTick(Math.Max(this.Minimum, Math.Min(this.Maximum, value + direction)));
bool greaterThan = direction > 0; //search for the next tick greater than value?
// If the snapping brought us back to value, find the next tick point
if (next == value
&& !( greaterThan && value == Maximum) // Stop if searching up if already at Max
&& !(!greaterThan && value == Minimum)) // Stop if searching down if already at Min
{
// This property is rarely set so let's try to avoid the GetValue
// caching of the mutable default value
DoubleCollection ticks = null;
bool hasModifiers;
if (GetValueSource(TicksProperty, null, out hasModifiers)
!= BaseValueSourceInternal.Default || hasModifiers)
{
ticks = Ticks;
}
// If ticks collection is available, use it.
// Note that ticks may be unsorted.
if ((ticks != null) && (ticks.Count > 0))
{
for (int i = 0; i < ticks.Count; i++)
{
double tick = ticks[i];
// Find the smallest tick greater than value or the largest tick less than value
if ((greaterThan && DoubleUtil.GreaterThan(tick, value) && (DoubleUtil.LessThan(tick, next) || next == value))
||(!greaterThan && DoubleUtil.LessThan(tick, value) && (DoubleUtil.GreaterThan(tick, next) || next == value)))
{
next = tick;
}
}
}
else if (DoubleUtil.GreaterThan(TickFrequency, 0.0))
{
// Find the current tick we are at
double tickNumber = Math.Round((value - Minimum) / TickFrequency);
if (greaterThan)
tickNumber += 1.0;
else
tickNumber -= 1.0;
next = Minimum + tickNumber * TickFrequency;
}
}
// Update if we've found a better value
if (next != value)
{
this.Value = next;
}
}
}
#endregion Event Handlers
#region Override Functions
///
/// Creates AutomationPeer ( )
///
protected override AutomationPeer OnCreateAutomationPeer()
{
return new SliderAutomationPeer(this);
}
///
/// This is a class handler for MouseLeftButtonDown event.
/// The purpose of this handle is to move input focus to Slider when user pressed
/// mouse left button on any part of slider that is not focusable.
///
///
///
private static void _OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if(e.ChangedButton != MouseButton.Left) return;
Slider slider = (Slider)sender;
// When someone click on the Slider's part, and it's not focusable
// Slider need to take the focus in order to process keyboard correctly
if (!slider.IsKeyboardFocusWithin)
{
e.Handled = slider.Focus() || e.Handled;
}
}
///
/// Perform arrangement of slider's children
///
///
protected override Size ArrangeOverride(Size finalSize)
{
Size size = base.ArrangeOverride(finalSize);
UpdateSelectionRangeElementPositionAndSize();
return size;
}
///
/// Update SelectionRange Length.
///
///
///
protected override void OnValueChanged(double oldValue, double newValue)
{
base.OnValueChanged(oldValue, newValue);
UpdateSelectionRangeElementPositionAndSize();
}
///
/// Slider locates the SelectionRangeElement when its visual tree is created
///
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
SelectionRangeElement = GetTemplateChild(SelectionRangeElementName) as FrameworkElement;
Track = GetTemplateChild(TrackName) as Track;
if (_autoToolTip != null)
{
_autoToolTip.PlacementTarget = Track != null ? Track.Thumb : null;
}
}
#endregion Override Functions
#region Virtual Functions
///
/// Call when Slider.IncreaseLarge command is invoked.
///
protected virtual void OnIncreaseLarge()
{
MoveToNextTick(this.LargeChange);
}
///
/// Call when Slider.DecreaseLarge command is invoked.
///
protected virtual void OnDecreaseLarge()
{
MoveToNextTick(-this.LargeChange);
}
///
/// Call when Slider.IncreaseSmall command is invoked.
///
protected virtual void OnIncreaseSmall()
{
MoveToNextTick(this.SmallChange);
}
///
/// Call when Slider.DecreaseSmall command is invoked.
///
protected virtual void OnDecreaseSmall()
{
MoveToNextTick(-this.SmallChange);
}
///
/// Call when Slider.MaximizeValue command is invoked.
///
protected virtual void OnMaximizeValue()
{
this.Value = this.Maximum;
}
///
/// Call when Slider.MinimizeValue command is invoked.
///
protected virtual void OnMinimizeValue()
{
this.Value = this.Minimum;
}
#endregion Virtual Functions
#region Helper Functions
///
/// Helper function for value update.
/// This function will also snap the value to tick, if IsSnapToTickEnabled is true.
///
///
private void UpdateValue(double value)
{
Double snappedValue = SnapToTick(value);
if (snappedValue != Value)
{
Value = Math.Max(this.Minimum, Math.Min(this.Maximum, snappedValue));
}
}
///
/// Validate input value in Slider (LargeChange, SmallChange, SelectionStart, SelectionEnd, and TickFrequency).
///
///
/// Returns False if value is NaN or NegativeInfinity or PositiveInfinity. Otherwise, returns True.
private static bool IsValidDoubleValue(object value)
{
double d = (double)value;
return !(DoubleUtil.IsNaN(d) || double.IsInfinity(d));
}
#endregion Helper Functions
#region Private Fields
private const string TrackName = "PART_Track";
private const string SelectionRangeElementName = "PART_SelectionRange";
// Slider required parts
private FrameworkElement _selectionRangeElement;
private Track _track;
private ToolTip _autoToolTip = null;
private object _thumbOriginalToolTip = null;
#endregion Private Fields
#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
}
}
// 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
- ValidationErrorEventArgs.cs
- metadatamappinghashervisitor.hashsourcebuilder.cs
- DetailsViewModeEventArgs.cs
- CollectionChange.cs
- CheckBoxAutomationPeer.cs
- BaseUriHelper.cs
- RemoveStoryboard.cs
- DataGridColumn.cs
- Grammar.cs
- ClipboardData.cs
- DocumentCollection.cs
- InvokeGenerator.cs
- selecteditemcollection.cs
- DecimalStorage.cs
- AutomationIdentifierGuids.cs
- UserThread.cs
- DefaultClaimSet.cs
- SettingsProperty.cs
- InputScopeAttribute.cs
- DataGridViewCellErrorTextNeededEventArgs.cs
- Control.cs
- BitmapDecoder.cs
- COM2ColorConverter.cs
- ProcessHostServerConfig.cs
- EmptyCollection.cs
- DesignerActionKeyboardBehavior.cs
- XamlInterfaces.cs
- ErrorRuntimeConfig.cs
- PtsHelper.cs
- DataRowExtensions.cs
- ComboBoxRenderer.cs
- ProxyWebPartManager.cs
- GenericUriParser.cs
- Filter.cs
- FrameworkContextData.cs
- SafeNativeMethods.cs
- ToolStripKeyboardHandlingService.cs
- OciEnlistContext.cs
- SelectedCellsChangedEventArgs.cs
- RowSpanVector.cs
- BasicViewGenerator.cs
- ActivationProxy.cs
- _DigestClient.cs
- DateTime.cs
- InitializerFacet.cs
- AsymmetricSignatureDeformatter.cs
- ProtectedConfigurationSection.cs
- PassportAuthentication.cs
- SmiConnection.cs
- AnyReturnReader.cs
- CopyOnWriteList.cs
- OleDbMetaDataFactory.cs
- DefaultValueMapping.cs
- TextTreeInsertElementUndoUnit.cs
- RegexTree.cs
- DataServiceHost.cs
- JournalEntryListConverter.cs
- DesignTimeResourceProviderFactoryAttribute.cs
- ValidationErrorInfo.cs
- DataObjectFieldAttribute.cs
- VScrollBar.cs
- RSAPKCS1KeyExchangeDeformatter.cs
- QueryCacheKey.cs
- ErrorFormatterPage.cs
- CodeObject.cs
- recordstatefactory.cs
- HostingEnvironmentSection.cs
- WorkflowApplicationAbortedException.cs
- AnnotationHighlightLayer.cs
- DefaultProxySection.cs
- __Filters.cs
- HashSet.cs
- StylusPlugin.cs
- CodeArgumentReferenceExpression.cs
- TextEditorTyping.cs
- TypeGeneratedEventArgs.cs
- RegexGroup.cs
- RegexFCD.cs
- TextSchema.cs
- AuthStoreRoleProvider.cs
- VirtualPath.cs
- DrawItemEvent.cs
- BridgeDataRecord.cs
- DataGridViewBand.cs
- DataTableCollection.cs
- FilterQueryOptionExpression.cs
- BuildResult.cs
- RemoteWebConfigurationHost.cs
- LongSumAggregationOperator.cs
- MyContact.cs
- NativeRightsManagementAPIsStructures.cs
- ObjectHelper.cs
- IMembershipProvider.cs
- Header.cs
- SqlPersistenceWorkflowInstanceDescription.cs
- VerificationException.cs
- BinaryMethodMessage.cs
- XpsFixedPageReaderWriter.cs
- XmlChoiceIdentifierAttribute.cs
- DataTableMappingCollection.cs