From 3d507136ee5136ac7a901eb250d4c44c0976e3af Mon Sep 17 00:00:00 2001 From: Adam Riyadi Date: Sat, 6 Aug 2016 17:45:57 +0700 Subject: [PATCH] Add Command, CommandParameter & CommandTarget to ToggleSwitchBase --- Common/RelayCommand.cs | 31 + Common/ToggleSwitchBase.cs | 1769 ++++++++++++++++------------- WPF/Demo/Controls/RelayCommand.cs | 34 + WPF/Demo/Demo.csproj | 1 + WPF/Demo/DemoViewModel.cs | 90 +- WPF/Demo/Views/Basics.xaml | 18 +- 6 files changed, 1087 insertions(+), 856 deletions(-) create mode 100644 Common/RelayCommand.cs create mode 100644 WPF/Demo/Controls/RelayCommand.cs diff --git a/Common/RelayCommand.cs b/Common/RelayCommand.cs new file mode 100644 index 0000000..5d78bd3 --- /dev/null +++ b/Common/RelayCommand.cs @@ -0,0 +1,31 @@ + +namespace Demo.Controls +{ + public class RelayCommand : ICommand + { + private Action execute; + private Func canExecute; + + public event EventHandler CanExecuteChanged + { + add { CommandManager.RequerySuggested += value; } + remove { CommandManager.RequerySuggested -= value; } + } + + public RelayCommand(Action execute, Func canExecute = null) + { + this.execute = execute; + this.canExecute = canExecute; + } + + public bool CanExecute(object parameter) + { + return this.canExecute == null || this.canExecute(parameter); + } + + public void Execute(object parameter) + { + this.execute(parameter); + } + } +} \ No newline at end of file diff --git a/Common/ToggleSwitchBase.cs b/Common/ToggleSwitchBase.cs index 9913091..8ea10d8 100644 --- a/Common/ToggleSwitchBase.cs +++ b/Common/ToggleSwitchBase.cs @@ -10,6 +10,7 @@ //----------------------------------------------------------------------- using System; using System.ComponentModel; +using System.Diagnostics; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; @@ -20,129 +21,129 @@ namespace ToggleSwitch { - /// - /// Base class for the toggle switch control. - /// - [TemplateVisualState(Name = NormalState, GroupName = CommonStates)] - [TemplateVisualState(Name = DisabledState, GroupName = CommonStates)] - [TemplateVisualState(Name = MouseOverState, GroupName = CommonStates)] - [TemplateVisualState(Name = FocusedState, GroupName = FocusStates)] - [TemplateVisualState(Name = UnfocusedState, GroupName = FocusStates)] - [TemplateVisualState(Name = CheckedState, GroupName = CheckStates)] - [TemplateVisualState(Name = UncheckedState, GroupName = CheckStates)] - [TemplateVisualState(Name = DraggingState + CheckedState, GroupName = CheckStates)] - [TemplateVisualState(Name = DraggingState + UncheckedState, GroupName = CheckStates)] - [TemplatePart(Name = SwitchCheckedPart, Type = typeof(Control))] - [TemplatePart(Name = SwitchUncheckedPart, Type = typeof(Control))] - [TemplatePart(Name = SwitchThumbPart, Type = typeof(Thumb))] - [TemplatePart(Name = SwitchRootPart, Type = typeof(FrameworkElement))] - [TemplatePart(Name = SwitchTrackPart, Type = typeof(FrameworkElement))] - [Description("A control which when clicked or dragged toggles between on and off states.")] - public abstract class ToggleSwitchBase : Control - { - #region Constants - - private const string CommonStates = "CommonStates"; - private const string NormalState = "Normal"; - private const string DisabledState = "Disabled"; - private const string MouseOverState = "MouseOver"; - - private const string CheckStates = "CheckStates"; - private const string CheckedState = "Checked"; - private const string DraggingState = "Dragging"; - private const string UncheckedState = "Unchecked"; - - private const string FocusStates = "FocusStates"; - private const string FocusedState = "Focused"; - private const string UnfocusedState = "Unfocused"; - - private const string SwitchRootPart = "SwitchRoot"; - private const string SwitchCheckedPart = "SwitchChecked"; - private const string SwitchUncheckedPart = "SwitchUnchecked"; - private const string SwitchThumbPart = "SwitchThumb"; - private const string SwitchTrackPart = "SwitchTrack"; - - private const string CommonPropertiesCategory = "Common Properties"; - private const string AppearanceCategory = "Appearance"; - - #endregion - - #region Fields + /// + /// Base class for the toggle switch control. + /// + [TemplateVisualState(Name = NormalState, GroupName = CommonStates)] + [TemplateVisualState(Name = DisabledState, GroupName = CommonStates)] + [TemplateVisualState(Name = MouseOverState, GroupName = CommonStates)] + [TemplateVisualState(Name = FocusedState, GroupName = FocusStates)] + [TemplateVisualState(Name = UnfocusedState, GroupName = FocusStates)] + [TemplateVisualState(Name = CheckedState, GroupName = CheckStates)] + [TemplateVisualState(Name = UncheckedState, GroupName = CheckStates)] + [TemplateVisualState(Name = DraggingState + CheckedState, GroupName = CheckStates)] + [TemplateVisualState(Name = DraggingState + UncheckedState, GroupName = CheckStates)] + [TemplatePart(Name = SwitchCheckedPart, Type = typeof(Control))] + [TemplatePart(Name = SwitchUncheckedPart, Type = typeof(Control))] + [TemplatePart(Name = SwitchThumbPart, Type = typeof(Thumb))] + [TemplatePart(Name = SwitchRootPart, Type = typeof(FrameworkElement))] + [TemplatePart(Name = SwitchTrackPart, Type = typeof(FrameworkElement))] + [Description("A control which when clicked or dragged toggles between on and off states.")] + public abstract class ToggleSwitchBase : Control, ICommandSource + { + #region Constants + + private const string CommonStates = "CommonStates"; + private const string NormalState = "Normal"; + private const string DisabledState = "Disabled"; + private const string MouseOverState = "MouseOver"; + + private const string CheckStates = "CheckStates"; + private const string CheckedState = "Checked"; + private const string DraggingState = "Dragging"; + private const string UncheckedState = "Unchecked"; + + private const string FocusStates = "FocusStates"; + private const string FocusedState = "Focused"; + private const string UnfocusedState = "Unfocused"; + + private const string SwitchRootPart = "SwitchRoot"; + private const string SwitchCheckedPart = "SwitchChecked"; + private const string SwitchUncheckedPart = "SwitchUnchecked"; + private const string SwitchThumbPart = "SwitchThumb"; + private const string SwitchTrackPart = "SwitchTrack"; + + private const string CommonPropertiesCategory = "Common Properties"; + private const string AppearanceCategory = "Appearance"; + + #endregion + + #region Fields - /// - /// True if the mouse has been captured by this control, false otherwise. - /// - private bool _isMouseCaptured; + /// + /// True if the mouse has been captured by this control, false otherwise. + /// + private bool _isMouseCaptured; - /// - /// True if the SPACE key is currently pressed, false otherwise. - /// - private bool _isSpaceKeyDown; + /// + /// True if the SPACE key is currently pressed, false otherwise. + /// + private bool _isSpaceKeyDown; - /// - /// True if the mouse's left button is currently down, false otherwise. - /// - private bool _isMouseLeftButtonDown; + /// + /// True if the mouse's left button is currently down, false otherwise. + /// + private bool _isMouseLeftButtonDown; - /// - /// Last known position of the mouse with respect to this Button. - /// - private Point _mousePosition; + /// + /// Last known position of the mouse with respect to this Button. + /// + private Point _mousePosition; - /// - /// True if visual state changes are suspended; false otherwise. - /// - private bool _suspendStateChanges; + /// + /// True if visual state changes are suspended; false otherwise. + /// + private bool _suspendStateChanges; - #endregion + #endregion - #region Properties + #region Properties - protected Thumb SwitchThumb { get; set; } - protected Control SwitchChecked { get; set; } - protected Control SwitchUnchecked { get; set; } - protected FrameworkElement SwitchRoot { get; set; } - protected FrameworkElement SwitchTrack { get; set; } + protected Thumb SwitchThumb { get; set; } + protected Control SwitchChecked { get; set; } + protected Control SwitchUnchecked { get; set; } + protected FrameworkElement SwitchRoot { get; set; } + protected FrameworkElement SwitchTrack { get; set; } - /// - /// The current offset of the Thumb. - /// - protected abstract double Offset { get; set; } + /// + /// The current offset of the Thumb. + /// + protected abstract double Offset { get; set; } - /// - /// The current offset of the Thumb when it's in the Checked state. - /// - protected double CheckedOffset { get; set; } + /// + /// The current offset of the Thumb when it's in the Checked state. + /// + protected double CheckedOffset { get; set; } - /// - /// The current offset of the Thumb when it's in the Unchecked state. - /// - protected double UncheckedOffset { get; set; } + /// + /// The current offset of the Thumb when it's in the Unchecked state. + /// + protected double UncheckedOffset { get; set; } - /// - /// The offset of the thumb while it's being dragged. - /// - protected double DragOffset { get; set; } + /// + /// The offset of the thumb while it's being dragged. + /// + protected double DragOffset { get; set; } - /// - /// Gets or sets whether the thumb position is being manipulated. - /// - protected bool IsDragging { get; set; } + /// + /// Gets or sets whether the thumb position is being manipulated. + /// + protected bool IsDragging { get; set; } - /// - /// Gets a value that indicates whether a ToggleSwitch is currently pressed. - /// - public bool IsPressed { get; protected set; } + /// + /// Gets a value that indicates whether a ToggleSwitch is currently pressed. + /// + public bool IsPressed { get; protected set; } - protected abstract PropertyPath SlidePropertyPath { get; } + protected abstract PropertyPath SlidePropertyPath { get; } - #endregion + #endregion - #region Dependency Properties + #region Dependency Properties #if SILVERLIGHT - #region IsFocused + #region IsFocused /// /// Gets a value that determines whether this element has logical focus. @@ -163,9 +164,9 @@ public bool IsFocused public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.Register("IsFocused", typeof(bool), typeof(ToggleSwitchBase), null); - #endregion IsFocused + #endregion IsFocused - #region IsMouseOver + #region IsMouseOver /// /// Gets a value indicating whether the mouse pointer is located over @@ -188,309 +189,309 @@ public bool IsMouseOver public static readonly DependencyProperty IsMouseOverProperty = DependencyProperty.Register("IsMouseOver", typeof(bool), typeof(ToggleSwitchBase), null); - #endregion + #endregion #endif - #region ContentTemplate (DependencyProperty) + #region ContentTemplate (DependencyProperty) - /// - /// DependencyProperty for the ControlTemplate property. - /// - public static readonly DependencyProperty ContentTemplateProperty = - DependencyProperty.Register("ContentTemplate", typeof(ControlTemplate), typeof(ToggleSwitchBase), + /// + /// DependencyProperty for the ControlTemplate property. + /// + public static readonly DependencyProperty ContentTemplateProperty = + DependencyProperty.Register("ContentTemplate", typeof(ControlTemplate), typeof(ToggleSwitchBase), #if SILVERLIGHT new PropertyMetadata(OnLayoutDependancyPropertyChanged)); #else - new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure, OnLayoutDependancyPropertyChanged)); + new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure, OnLayoutDependancyPropertyChanged)); #endif - /// - /// The template applied to the Checked and Unchecked content properties. - /// - [Description("The template applied to the Checked and Unchecked content properties.")] - public ControlTemplate ContentTemplate - { - get { return (ControlTemplate)GetValue(ContentTemplateProperty); } - set { SetValue(ContentTemplateProperty, value); } - } + /// + /// The template applied to the Checked and Unchecked content properties. + /// + [Description("The template applied to the Checked and Unchecked content properties.")] + public ControlTemplate ContentTemplate + { + get { return (ControlTemplate)GetValue(ContentTemplateProperty); } + set { SetValue(ContentTemplateProperty, value); } + } - #endregion + #endregion - #region CheckedContent (Dependency Property) + #region CheckedContent (Dependency Property) - /// - /// DependencyProperty for the CheckedContent property. - /// - public static readonly DependencyProperty CheckedContentProperty = - DependencyProperty.Register("CheckedContent", typeof(object), typeof(ToggleSwitchBase), + /// + /// DependencyProperty for the CheckedContent property. + /// + public static readonly DependencyProperty CheckedContentProperty = + DependencyProperty.Register("CheckedContent", typeof(object), typeof(ToggleSwitchBase), #if SILVERLIGHT new PropertyMetadata("ON", OnLayoutDependancyPropertyChanged)); #else - new FrameworkPropertyMetadata("ON", FrameworkPropertyMetadataOptions.AffectsArrange, OnLayoutDependancyPropertyChanged)); + new FrameworkPropertyMetadata("ON", FrameworkPropertyMetadataOptions.AffectsArrange, OnLayoutDependancyPropertyChanged)); #endif - /// - /// The content shown on the checked side of the toggle switch - /// - [Category(CommonPropertiesCategory)] - [Description("The content shown on the checked side of the toggle switch")] - public object CheckedContent - { - get { return GetValue(CheckedContentProperty); } - set { SetValue(CheckedContentProperty, value); } - } + /// + /// The content shown on the checked side of the toggle switch + /// + [Category(CommonPropertiesCategory)] + [Description("The content shown on the checked side of the toggle switch")] + public object CheckedContent + { + get { return GetValue(CheckedContentProperty); } + set { SetValue(CheckedContentProperty, value); } + } - #endregion + #endregion - #region CheckedForeground (Dependency Property) + #region CheckedForeground (Dependency Property) - /// - /// DependencyProperty for the CheckedForeground property. - /// - public static readonly DependencyProperty CheckedForegroundProperty = - DependencyProperty.Register("CheckedForeground", typeof(Brush), typeof(ToggleSwitchBase), null); + /// + /// DependencyProperty for the CheckedForeground property. + /// + public static readonly DependencyProperty CheckedForegroundProperty = + DependencyProperty.Register("CheckedForeground", typeof(Brush), typeof(ToggleSwitchBase), null); - /// - /// The brush used for the foreground of the checked side of the toggle switch. - /// - [Description("The brush used for the foreground of the checked side of the toggle switch.")] - public Brush CheckedForeground - { - get { return (Brush)GetValue(CheckedForegroundProperty); } - set { SetValue(CheckedForegroundProperty, value); } - } + /// + /// The brush used for the foreground of the checked side of the toggle switch. + /// + [Description("The brush used for the foreground of the checked side of the toggle switch.")] + public Brush CheckedForeground + { + get { return (Brush)GetValue(CheckedForegroundProperty); } + set { SetValue(CheckedForegroundProperty, value); } + } - #endregion + #endregion - #region CheckedBackground (Dependency Property) + #region CheckedBackground (Dependency Property) - /// - /// DependencyProperty for the CheckedBackground property. - /// - public static readonly DependencyProperty CheckedBackgroundProperty = - DependencyProperty.Register("CheckedBackground", typeof(Brush), typeof(ToggleSwitchBase), null); + /// + /// DependencyProperty for the CheckedBackground property. + /// + public static readonly DependencyProperty CheckedBackgroundProperty = + DependencyProperty.Register("CheckedBackground", typeof(Brush), typeof(ToggleSwitchBase), null); - /// - /// The brush used for the background of the checked side of the toggle switch. - /// - [Description("The brush used for the background of the checked side of the toggle switch.")] - public Brush CheckedBackground - { - get { return (Brush)GetValue(CheckedBackgroundProperty); } - set { SetValue(CheckedBackgroundProperty, value); } - } + /// + /// The brush used for the background of the checked side of the toggle switch. + /// + [Description("The brush used for the background of the checked side of the toggle switch.")] + public Brush CheckedBackground + { + get { return (Brush)GetValue(CheckedBackgroundProperty); } + set { SetValue(CheckedBackgroundProperty, value); } + } - #endregion + #endregion - #region UncheckedContent (Dependency Property) + #region UncheckedContent (Dependency Property) - /// - /// DependencyProperty for the UncheckedContent property. - /// - public static readonly DependencyProperty UncheckedContentProperty = - DependencyProperty.Register("UncheckedContent", typeof(object), typeof(ToggleSwitchBase), + /// + /// DependencyProperty for the UncheckedContent property. + /// + public static readonly DependencyProperty UncheckedContentProperty = + DependencyProperty.Register("UncheckedContent", typeof(object), typeof(ToggleSwitchBase), #if SILVERLIGHT new PropertyMetadata("OFF", OnLayoutDependancyPropertyChanged)); #else - new FrameworkPropertyMetadata("OFF", FrameworkPropertyMetadataOptions.AffectsArrange, OnLayoutDependancyPropertyChanged)); + new FrameworkPropertyMetadata("OFF", FrameworkPropertyMetadataOptions.AffectsArrange, OnLayoutDependancyPropertyChanged)); #endif - /// - /// The content shown on the unchecked side of the toggle switch. - /// - [Category(CommonPropertiesCategory)] - [Description("The content shown on the unchecked side of the toggle switch.")] - public object UncheckedContent - { - get { return GetValue(UncheckedContentProperty); } - set { SetValue(UncheckedContentProperty, value); } - } - - #endregion - - #region UncheckedForeground (Dependency Property) - - /// - /// DependencyProperty for the UncheckedForeground property. - /// - public static readonly DependencyProperty UncheckedForegroundProperty = - DependencyProperty.Register("UncheckedForeground", typeof(Brush), typeof(ToggleSwitchBase), null); + /// + /// The content shown on the unchecked side of the toggle switch. + /// + [Category(CommonPropertiesCategory)] + [Description("The content shown on the unchecked side of the toggle switch.")] + public object UncheckedContent + { + get { return GetValue(UncheckedContentProperty); } + set { SetValue(UncheckedContentProperty, value); } + } - /// - /// The brush used for the foreground of the Unchecked side of the toggle switch. - /// - [Description("The brush used for the foreground of the Unchecked side of the toggle switch.")] - public Brush UncheckedForeground - { - get { return (Brush)GetValue(UncheckedForegroundProperty); } - set { SetValue(UncheckedForegroundProperty, value); } - } + #endregion - #endregion + #region UncheckedForeground (Dependency Property) - #region UncheckedBackground (Dependency Property) + /// + /// DependencyProperty for the UncheckedForeground property. + /// + public static readonly DependencyProperty UncheckedForegroundProperty = + DependencyProperty.Register("UncheckedForeground", typeof(Brush), typeof(ToggleSwitchBase), null); - /// - /// DependencyProperty for the UncheckedBackground property. - /// - public static readonly DependencyProperty UncheckedBackgroundProperty = - DependencyProperty.Register("UncheckedBackground", typeof(Brush), typeof(ToggleSwitchBase), null); + /// + /// The brush used for the foreground of the Unchecked side of the toggle switch. + /// + [Description("The brush used for the foreground of the Unchecked side of the toggle switch.")] + public Brush UncheckedForeground + { + get { return (Brush)GetValue(UncheckedForegroundProperty); } + set { SetValue(UncheckedForegroundProperty, value); } + } - /// - /// The brush used for the background of the Unchecked side of the toggle switch. - /// - [Description("The brush used for the background of the Unchecked side of the toggle switch.")] - public Brush UncheckedBackground - { - get { return (Brush)GetValue(UncheckedBackgroundProperty); } - set { SetValue(UncheckedBackgroundProperty, value); } - } + #endregion - #endregion + #region UncheckedBackground (Dependency Property) - #region Elasticity (Dependency Property) + /// + /// DependencyProperty for the UncheckedBackground property. + /// + public static readonly DependencyProperty UncheckedBackgroundProperty = + DependencyProperty.Register("UncheckedBackground", typeof(Brush), typeof(ToggleSwitchBase), null); - /// - /// DependencyProperty for the Elasticity property. - /// - public static readonly DependencyProperty ElasticityProperty = - DependencyProperty.Register("Elasticity", typeof(double), typeof(ToggleSwitchBase), new PropertyMetadata(0.5)); + /// + /// The brush used for the background of the Unchecked side of the toggle switch. + /// + [Description("The brush used for the background of the Unchecked side of the toggle switch.")] + public Brush UncheckedBackground + { + get { return (Brush)GetValue(UncheckedBackgroundProperty); } + set { SetValue(UncheckedBackgroundProperty, value); } + } - /// - /// Determines the percentage of the way the thumb must be dragged before the switch changes it's IsChecked state. - /// - /// - /// This value must be within the range of 0.0 - 1.0. - /// - [Category(CommonPropertiesCategory)] - [Description("Determines the percentage of the way the thumb must be dragged before the switch changes it's IsChecked state.")] - public double Elasticity - { - get { return ((double)GetValue(ElasticityProperty)).Clamp(0.0, 1.0); } - set { SetValue(ElasticityProperty, value.Clamp(0, 1.0)); } - } + #endregion + + #region Elasticity (Dependency Property) + + /// + /// DependencyProperty for the Elasticity property. + /// + public static readonly DependencyProperty ElasticityProperty = + DependencyProperty.Register("Elasticity", typeof(double), typeof(ToggleSwitchBase), new PropertyMetadata(0.5)); + + /// + /// Determines the percentage of the way the thumb must be dragged before the switch changes it's IsChecked state. + /// + /// + /// This value must be within the range of 0.0 - 1.0. + /// + [Category(CommonPropertiesCategory)] + [Description("Determines the percentage of the way the thumb must be dragged before the switch changes it's IsChecked state.")] + public double Elasticity + { + get { return ((double)GetValue(ElasticityProperty)).Clamp(0.0, 1.0); } + set { SetValue(ElasticityProperty, value.Clamp(0, 1.0)); } + } - #endregion + #endregion - #region ThumbTemplate (DependencyProperty) + #region ThumbTemplate (DependencyProperty) - /// - /// DependencyProperty for the ThumbTemplate property. - /// - public static readonly DependencyProperty ThumbTemplateProperty = - DependencyProperty.Register("ThumbTemplate", typeof(ControlTemplate), typeof(ToggleSwitchBase), + /// + /// DependencyProperty for the ThumbTemplate property. + /// + public static readonly DependencyProperty ThumbTemplateProperty = + DependencyProperty.Register("ThumbTemplate", typeof(ControlTemplate), typeof(ToggleSwitchBase), #if SILVERLIGHT new PropertyMetadata(OnLayoutDependancyPropertyChanged)); #else - new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure, OnLayoutDependancyPropertyChanged)); + new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure, OnLayoutDependancyPropertyChanged)); #endif - /// - /// The thumb's control template. - /// - [Description("The thumb's control template.")] - public ControlTemplate ThumbTemplate - { - get { return (ControlTemplate)GetValue(ThumbTemplateProperty); } - set { SetValue(ThumbTemplateProperty, value); } - } + /// + /// The thumb's control template. + /// + [Description("The thumb's control template.")] + public ControlTemplate ThumbTemplate + { + get { return (ControlTemplate)GetValue(ThumbTemplateProperty); } + set { SetValue(ThumbTemplateProperty, value); } + } - #endregion + #endregion - #region ThumbBrush (Dependency Property) + #region ThumbBrush (Dependency Property) - /// - /// DependencyProperty for the ThumbBrush property. - /// - public static readonly DependencyProperty ThumbBrushProperty = - DependencyProperty.Register("ThumbBrush", typeof(Brush), typeof(ToggleSwitchBase), null); + /// + /// DependencyProperty for the ThumbBrush property. + /// + public static readonly DependencyProperty ThumbBrushProperty = + DependencyProperty.Register("ThumbBrush", typeof(Brush), typeof(ToggleSwitchBase), null); - /// - /// The brush used to fill the thumb. - /// - [Description("The brush used to fill the thumb.")] - public Brush ThumbBrush - { - get { return (Brush)GetValue(ThumbBrushProperty); } - set { SetValue(ThumbBrushProperty, value); } - } + /// + /// The brush used to fill the thumb. + /// + [Description("The brush used to fill the thumb.")] + public Brush ThumbBrush + { + get { return (Brush)GetValue(ThumbBrushProperty); } + set { SetValue(ThumbBrushProperty, value); } + } - #endregion + #endregion - #region ThumbSize (DependencyProperty) + #region ThumbSize (DependencyProperty) - /// - /// DependencyProperty for the ThumbSize property. - /// - public static readonly DependencyProperty ThumbSizeProperty = - DependencyProperty.Register("ThumbSize", typeof(double), typeof(ToggleSwitchBase), + /// + /// DependencyProperty for the ThumbSize property. + /// + public static readonly DependencyProperty ThumbSizeProperty = + DependencyProperty.Register("ThumbSize", typeof(double), typeof(ToggleSwitchBase), #if SILVERLIGHT new PropertyMetadata(40.0, OnLayoutDependancyPropertyChanged)); #else - new FrameworkPropertyMetadata(40.0, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure, OnLayoutDependancyPropertyChanged)); + new FrameworkPropertyMetadata(40.0, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure, OnLayoutDependancyPropertyChanged)); #endif - /// - /// The size of the toggle switch's thumb. - /// - [Category(AppearanceCategory)] - [Description("The size of the toggle switch's thumb.")] - public double ThumbSize - { - get { return (double)GetValue(ThumbSizeProperty); } - set { SetValue(ThumbSizeProperty, value); } - } + /// + /// The size of the toggle switch's thumb. + /// + [Category(AppearanceCategory)] + [Description("The size of the toggle switch's thumb.")] + public double ThumbSize + { + get { return (double)GetValue(ThumbSizeProperty); } + set { SetValue(ThumbSizeProperty, value); } + } - #endregion + #endregion - #region IsChecked (DependencyProperty) + #region IsChecked (DependencyProperty) - /// - /// DependencyProperty for the IsChecked property. - /// - public static readonly DependencyProperty IsCheckedProperty = - DependencyProperty.Register("IsChecked", typeof(bool), typeof(ToggleSwitchBase), + /// + /// DependencyProperty for the IsChecked property. + /// + public static readonly DependencyProperty IsCheckedProperty = + DependencyProperty.Register("IsChecked", typeof(bool), typeof(ToggleSwitchBase), #if SILVERLIGHT new PropertyMetadata(false, OnIsCheckedChanged)); #else - new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsArrange, OnIsCheckedChanged)); + new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsArrange, OnIsCheckedChanged)); #endif - /// - /// Gets or sets whether the control is in the checked state. - /// - [Category(CommonPropertiesCategory)] - [Description("Gets or sets whether the control is in the checked state.")] - public bool IsChecked - { - get { return (bool)GetValue(IsCheckedProperty); } - set { SetValue(IsCheckedProperty, value); } - } + /// + /// Gets or sets whether the control is in the checked state. + /// + [Category(CommonPropertiesCategory)] + [Description("Gets or sets whether the control is in the checked state.")] + public bool IsChecked + { + get { return (bool)GetValue(IsCheckedProperty); } + set { SetValue(IsCheckedProperty, value); } + } - private static void OnIsCheckedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - var control = (ToggleSwitchBase)d; - - if (e.NewValue != e.OldValue) - { - if ((bool)e.NewValue) - { - control.InvokeChecked(new RoutedEventArgs()); - } - else - { - control.InvokeUnchecked(new RoutedEventArgs()); - } - } - - control.ChangeCheckStates(true); - } + private static void OnIsCheckedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = (ToggleSwitchBase)d; + + if (e.NewValue != e.OldValue) + { + if ((bool)e.NewValue) + { + control.InvokeChecked(new RoutedEventArgs()); + } + else + { + control.InvokeUnchecked(new RoutedEventArgs()); + } + } + + control.ChangeCheckStates(true); + } - #endregion + #endregion #if SILVERLIGHT - #region ZoomFactor (DependencyProperty) + #region ZoomFactor (DependencyProperty) /// /// DependencyProperty for the ZoomFactor property. @@ -509,150 +510,229 @@ public double ZoomFactor set { SetValue(ZoomFactorProperty, value); } } - #endregion + #endregion #endif - #endregion + #region Command (DependencyProperty) + + /// + /// DependencyProperty for the Command property. + /// + public static readonly DependencyProperty CommandProperty = + DependencyProperty.Register( + "Command", + typeof(ICommand), + typeof(ToggleSwitchBase), + new PropertyMetadata((ICommand)null, + new PropertyChangedCallback(CommandChanged))); + + public ICommand Command + { + get + { + return (ICommand)GetValue(CommandProperty); + } + set + { + SetValue(CommandProperty, value); + } + } - #region Events + private static void CommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ToggleSwitchBase tsb = (ToggleSwitchBase)d; + tsb.HookUpCommand((ICommand)e.OldValue, (ICommand)e.NewValue); + } + #endregion - /// - /// Event raised when the toggle switch is unchecked. - /// - public event RoutedEventHandler Unchecked; + #region CommandParameter (DependencyProperty) - protected void InvokeUnchecked(RoutedEventArgs e) - { - RoutedEventHandler handler = Unchecked; - if (handler != null) - { - handler(this, e); - } - } + /// + /// DependencyProperty for the CommandParameter property. + /// + public static readonly DependencyProperty CommandParameterProperty = + DependencyProperty.Register("CommandParameter", typeof(object), typeof(ToggleSwitchBase), new UIPropertyMetadata(null)); - /// - /// Event raised when the toggle switch is checked. - /// - public event RoutedEventHandler Checked; + public object CommandParameter + { + get { return (object)GetValue(CommandParameterProperty); } + set { SetValue(CommandParameterProperty, value); } + } + #endregion - protected void InvokeChecked(RoutedEventArgs e) - { - RoutedEventHandler handler = Checked; - if (handler != null) - { - handler(this, e); - } - } + #region CommandTarget (DependencyProperty) - #endregion + /// + /// DependencyProperty for the CommandTarget property. + /// + public static readonly DependencyProperty CommandTargetProperty = + DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(ToggleSwitchBase), new UIPropertyMetadata(null)); - /// - /// Initializes a new instance of the ToggleSwitchBase class. - /// - protected ToggleSwitchBase() - { - Loaded += delegate { UpdateVisualState(false); }; - IsEnabledChanged += OnIsEnabledChanged; - } + public IInputElement CommandTarget + { + get { return (IInputElement)GetValue(CommandTargetProperty); } + set { SetValue(CommandTargetProperty, value); } + } + #endregion - /// - /// Raised while dragging the Thumb. - /// - /// - /// - protected abstract void OnDragDelta(object sender, DragDeltaEventArgs e); - /// - /// Raised when the dragging of the Thumb has completed. - /// - /// - /// - protected abstract void OnDragCompleted(object sender, DragCompletedEventArgs e); + #endregion - /// - /// Recalculated the layout of the control. - /// - protected abstract void LayoutControls(); + #region Events - public override void OnApplyTemplate() - { - base.OnApplyTemplate(); + /// + /// Event raised when the toggle switch is unchecked. + /// + public event RoutedEventHandler Unchecked; - RemoveEventHandlers(); - GetTemplateChildren(); - AddEventHandlers(); + protected void InvokeUnchecked(RoutedEventArgs e) + { + RoutedEventHandler handler = Unchecked; + if (handler != null) + { + handler(this, e); + } + } - LayoutControls(); + /// + /// Event raised when the toggle switch is checked. + /// + public event RoutedEventHandler Checked; + + protected void InvokeChecked(RoutedEventArgs e) + { + RoutedEventHandler handler = Checked; + if (handler != null) + { + handler(this, e); + } + } - VisualStateManager.GoToState(this, IsEnabled ? NormalState : DisabledState, false); - ChangeCheckStates(false); - } + #endregion - /// - /// Initializes the control's template parts. - /// - protected virtual void GetTemplateChildren() - { - SwitchRoot = GetTemplateChild(SwitchRootPart) as FrameworkElement; - SwitchThumb = GetTemplateChild(SwitchThumbPart) as Thumb; - SwitchChecked = GetTemplateChild(SwitchCheckedPart) as Control; - SwitchUnchecked = GetTemplateChild(SwitchUncheckedPart) as Control; - SwitchTrack = GetTemplateChild(SwitchTrackPart) as FrameworkElement; - } + /// + /// Initializes a new instance of the ToggleSwitchBase class. + /// + protected ToggleSwitchBase() : base() + { + Loaded += delegate { UpdateVisualState(false); }; + IsEnabledChanged += OnIsEnabledChanged; + } - /// - /// Subscribe event listeners. - /// - protected virtual void AddEventHandlers() - { - if (SwitchThumb != null) - { - SwitchThumb.DragStarted += OnDragStarted; - SwitchThumb.DragDelta += OnDragDelta; - SwitchThumb.DragCompleted += OnDragCompleted; - } - SizeChanged += OnSizeChanged; - } + /// + /// Raised while dragging the Thumb. + /// + /// + /// + protected abstract void OnDragDelta(object sender, DragDeltaEventArgs e); - /// - /// Unsubscribe event listeners. - /// - protected virtual void RemoveEventHandlers() - { - if (SwitchThumb != null) - { - SwitchThumb.DragStarted -= OnDragStarted; - SwitchThumb.DragDelta -= OnDragDelta; - SwitchThumb.DragCompleted -= OnDragCompleted; - } - SizeChanged -= OnSizeChanged; - } + /// + /// Raised when the dragging of the Thumb has completed. + /// + /// + /// + protected abstract void OnDragCompleted(object sender, DragCompletedEventArgs e); - /// - /// Raised when a drag has started on the Thumb. - /// - /// - /// - protected virtual void OnDragStarted(object sender, DragStartedEventArgs e) - { - IsDragging = true; - DragOffset = Offset; - ChangeCheckStates(false); + /// + /// Recalculated the layout of the control. + /// + protected abstract void LayoutControls(); + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + RemoveEventHandlers(); + GetTemplateChildren(); + AddEventHandlers(); + + LayoutControls(); + + VisualStateManager.GoToState(this, IsEnabled ? NormalState : DisabledState, false); + ChangeCheckStates(false); + } + + /// + /// Initializes the control's template parts. + /// + protected virtual void GetTemplateChildren() + { + SwitchRoot = GetTemplateChild(SwitchRootPart) as FrameworkElement; + SwitchThumb = GetTemplateChild(SwitchThumbPart) as Thumb; + SwitchChecked = GetTemplateChild(SwitchCheckedPart) as Control; + SwitchUnchecked = GetTemplateChild(SwitchUncheckedPart) as Control; + SwitchTrack = GetTemplateChild(SwitchTrackPart) as FrameworkElement; + } + + /// + /// Subscribe event listeners. + /// + protected virtual void AddEventHandlers() + { + if (SwitchThumb != null) + { + SwitchThumb.DragStarted += OnDragStarted; + SwitchThumb.DragDelta += OnDragDelta; + SwitchThumb.DragCompleted += OnDragCompleted; + } + SizeChanged += OnSizeChanged; + } + + /// + /// Unsubscribe event listeners. + /// + protected virtual void RemoveEventHandlers() + { + if (SwitchThumb != null) + { + SwitchThumb.DragStarted -= OnDragStarted; + SwitchThumb.DragDelta -= OnDragDelta; + SwitchThumb.DragCompleted -= OnDragCompleted; + } + SizeChanged -= OnSizeChanged; + } + + /// + /// Raised when a drag has started on the Thumb. + /// + /// + /// + protected virtual void OnDragStarted(object sender, DragStartedEventArgs e) + { + IsDragging = true; + DragOffset = Offset; + ChangeCheckStates(false); #if SILVERLIGHT CaptureMouseInternal(); #endif - } + } - /// - /// Called when the control is clicked. - /// - protected void OnClick() - { + /// + /// Called when the control is clicked. + /// + protected void OnClick() + { #if SILVERLIGHT IsChecked = !IsChecked; #else SetCurrentValue(IsCheckedProperty, !IsChecked); #endif + + #region Execute Command + if (this.Command != null) + { + RoutedCommand command = Command as RoutedCommand; + + if (command != null) + { + command.Execute(CommandParameter, CommandTarget); + } + else + { + ((ICommand)Command).Execute(CommandParameter); + } + } + #endregion } /// @@ -661,65 +741,65 @@ protected void OnClick() /// /// protected virtual void OnSizeChanged(object sender, SizeChangedEventArgs e) - { - LayoutControls(); - } + { + LayoutControls(); + } - /// - /// Capture the mouse. - /// - internal void CaptureMouseInternal() - { - if (!_isMouseCaptured) - { - _isMouseCaptured = CaptureMouse(); - } - } + /// + /// Capture the mouse. + /// + internal void CaptureMouseInternal() + { + if (!_isMouseCaptured) + { + _isMouseCaptured = CaptureMouse(); + } + } - /// - /// Release mouse capture if we already had it. - /// - protected internal void ReleaseMouseCaptureInternal() - { - ReleaseMouseCapture(); - _isMouseCaptured = false; - } + /// + /// Release mouse capture if we already had it. + /// + protected internal void ReleaseMouseCaptureInternal() + { + ReleaseMouseCapture(); + _isMouseCaptured = false; + } - /// - /// Raised when a dependency property that affects the control's layout has changed. - /// - /// The ToggleSwitch control - /// - private static void OnLayoutDependancyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - if (e.NewValue != e.OldValue) - { - ((ToggleSwitchBase)d).LayoutControls(); - } - } + /// + /// Raised when a dependency property that affects the control's layout has changed. + /// + /// The ToggleSwitch control + /// + private static void OnLayoutDependancyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (e.NewValue != e.OldValue) + { + ((ToggleSwitchBase)d).LayoutControls(); + } + } - /// - /// Called when the IsEnabled property changes. - /// - /// - /// - private void OnIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) - { - _suspendStateChanges = true; - if (!IsEnabled) - { - IsPressed = false; + /// + /// Called when the IsEnabled property changes. + /// + /// + /// + private void OnIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) + { + _suspendStateChanges = true; + if (!IsEnabled) + { + IsPressed = false; #if SILVERLIGHT IsMouseOver = false; #endif - _isMouseCaptured = false; - _isSpaceKeyDown = false; - _isMouseLeftButtonDown = false; - } + _isMouseCaptured = false; + _isSpaceKeyDown = false; + _isMouseLeftButtonDown = false; + } - _suspendStateChanges = false; - UpdateVisualState(); - } + _suspendStateChanges = false; + UpdateVisualState(); + } #if SILVERLIGHT /// @@ -734,151 +814,151 @@ protected override void OnGotFocus(RoutedEventArgs e) } #endif - /// - /// Responds to the LostFocus event. - /// - /// The event data for the LostFocus event. - protected override void OnLostFocus(RoutedEventArgs e) - { - base.OnLostFocus(e); + /// + /// Responds to the LostFocus event. + /// + /// The event data for the LostFocus event. + protected override void OnLostFocus(RoutedEventArgs e) + { + base.OnLostFocus(e); #if SILVERLIGHT IsFocused = false; #endif - IsPressed = false; - ReleaseMouseCaptureInternal(); - _isSpaceKeyDown = false; + IsPressed = false; + ReleaseMouseCaptureInternal(); + _isSpaceKeyDown = false; - _suspendStateChanges = false; - UpdateVisualState(); - } + _suspendStateChanges = false; + UpdateVisualState(); + } - /// - /// Responds to the KeyDown event. - /// - /// The event data for the KeyDown event. - protected override void OnKeyDown(KeyEventArgs e) - { - base.OnKeyDown(e); - if (e.Handled) - { - return; - } - - if (OnKeyDownInternal(e.Key)) - { - e.Handled = true; - } - } + /// + /// Responds to the KeyDown event. + /// + /// The event data for the KeyDown event. + protected override void OnKeyDown(KeyEventArgs e) + { + base.OnKeyDown(e); + if (e.Handled) + { + return; + } + + if (OnKeyDownInternal(e.Key)) + { + e.Handled = true; + } + } - /// - /// Handles the KeyDown event for ButtonBase. - /// - /// - /// The keyboard key associated with the event. - /// - /// True if the event was handled, false otherwise. - /// - /// This method exists for the purpose of unit testing since we can't - /// set KeyEventArgs.Key to simulate key press events. - /// - private bool OnKeyDownInternal(Key key) - { - bool handled = false; - - if (IsEnabled) - { - if (key == Key.Space) - { - if (!_isMouseCaptured && !_isSpaceKeyDown) - { - _isSpaceKeyDown = true; - IsPressed = true; - CaptureMouseInternal(); - - handled = true; - } - } - else if (key == Key.Enter) - { - _isSpaceKeyDown = false; - IsPressed = false; - ReleaseMouseCaptureInternal(); - - OnClick(); - - handled = true; - } - else if (_isSpaceKeyDown) - { - IsPressed = false; - _isSpaceKeyDown = false; - ReleaseMouseCaptureInternal(); - } - } - - return handled; - } + /// + /// Handles the KeyDown event for ButtonBase. + /// + /// + /// The keyboard key associated with the event. + /// + /// True if the event was handled, false otherwise. + /// + /// This method exists for the purpose of unit testing since we can't + /// set KeyEventArgs.Key to simulate key press events. + /// + private bool OnKeyDownInternal(Key key) + { + bool handled = false; + + if (IsEnabled) + { + if (key == Key.Space) + { + if (!_isMouseCaptured && !_isSpaceKeyDown) + { + _isSpaceKeyDown = true; + IsPressed = true; + CaptureMouseInternal(); + + handled = true; + } + } + else if (key == Key.Enter) + { + _isSpaceKeyDown = false; + IsPressed = false; + ReleaseMouseCaptureInternal(); + + OnClick(); + + handled = true; + } + else if (_isSpaceKeyDown) + { + IsPressed = false; + _isSpaceKeyDown = false; + ReleaseMouseCaptureInternal(); + } + } + + return handled; + } - /// - /// Responds to the KeyUp event. - /// - /// The event data for the KeyUp event. - protected override void OnKeyUp(KeyEventArgs e) - { - base.OnKeyUp(e); - if (e.Handled) - { - return; - } - - if (OnKeyUpInternal(e.Key)) - { - e.Handled = true; - } - } + /// + /// Responds to the KeyUp event. + /// + /// The event data for the KeyUp event. + protected override void OnKeyUp(KeyEventArgs e) + { + base.OnKeyUp(e); + if (e.Handled) + { + return; + } + + if (OnKeyUpInternal(e.Key)) + { + e.Handled = true; + } + } - /// - /// Handles the KeyUp event for ButtonBase. - /// - /// The keyboard key associated with the event. - /// True if the event was handled, false otherwise. - /// - /// This method exists for the purpose of unit testing since we can't - /// set KeyEventArgs.Key to simulate key press events. - /// - private bool OnKeyUpInternal(Key key) - { - bool handled = false; - - if (IsEnabled && (key == Key.Space)) - { - _isSpaceKeyDown = false; - - if (!_isMouseLeftButtonDown) - { - ReleaseMouseCaptureInternal(); - if (IsPressed) - { - OnClick(); - } - - IsPressed = false; - } - else if (_isMouseCaptured) - { - bool isValid = IsValidMousePosition(); - IsPressed = isValid; - if (!isValid) - { - ReleaseMouseCaptureInternal(); - } - } - - handled = true; - } - - return handled; - } + /// + /// Handles the KeyUp event for ButtonBase. + /// + /// The keyboard key associated with the event. + /// True if the event was handled, false otherwise. + /// + /// This method exists for the purpose of unit testing since we can't + /// set KeyEventArgs.Key to simulate key press events. + /// + private bool OnKeyUpInternal(Key key) + { + bool handled = false; + + if (IsEnabled && (key == Key.Space)) + { + _isSpaceKeyDown = false; + + if (!_isMouseLeftButtonDown) + { + ReleaseMouseCaptureInternal(); + if (IsPressed) + { + OnClick(); + } + + IsPressed = false; + } + else if (_isMouseCaptured) + { + bool isValid = IsValidMousePosition(); + IsPressed = isValid; + if (!isValid) + { + ReleaseMouseCaptureInternal(); + } + } + + handled = true; + } + + return handled; + } #if SILVERLIGHT /// @@ -906,190 +986,255 @@ protected override void OnMouseLeave(MouseEventArgs e) } #endif - /// - /// Responds to the MouseLeftButtonDown event. - /// - /// - /// The event data for the MouseLeftButtonDown event. - /// - protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) - { - base.OnMouseLeftButtonDown(e); - if (e.Handled) - { - return; - } - - _isMouseLeftButtonDown = true; + /// + /// Responds to the MouseLeftButtonDown event. + /// + /// + /// The event data for the MouseLeftButtonDown event. + /// + protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) + { + base.OnMouseLeftButtonDown(e); + if (e.Handled) + { + return; + } + + _isMouseLeftButtonDown = true; + + if (!IsEnabled) + { + return; + } + + e.Handled = true; + _suspendStateChanges = true; + Focus(); + + CaptureMouseInternal(); + if (_isMouseCaptured) + { + IsPressed = true; + } + + _suspendStateChanges = false; + UpdateVisualState(); + } - if (!IsEnabled) - { - return; - } + /// + /// Responds to the MouseLeftButtonUp event. + /// + /// + /// The event data for the MouseLeftButtonUp event. + /// + protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) + { + base.OnMouseLeftButtonUp(e); + if (e.Handled) + { + return; + } + + _isMouseLeftButtonDown = false; + + if (!IsEnabled) + { + return; + } + + e.Handled = true; + if (!_isSpaceKeyDown && IsPressed) + { + OnClick(); + } + + if (!_isSpaceKeyDown) + { + ReleaseMouseCaptureInternal(); + IsPressed = false; + } + } - e.Handled = true; - _suspendStateChanges = true; - Focus(); + /// + /// Responds to the MouseMove event. + /// + /// The event data for the MouseMove event. + protected override void OnMouseMove(MouseEventArgs e) + { + base.OnMouseMove(e); + _mousePosition = e.GetPosition(this); + + if (_isMouseLeftButtonDown && + IsEnabled && + _isMouseCaptured && + !_isSpaceKeyDown) + { + IsPressed = IsValidMousePosition(); + } + } - CaptureMouseInternal(); - if (_isMouseCaptured) - { - IsPressed = true; - } + /// + /// Determine if the mouse is above the button based on its last known + /// position. + /// + /// + /// True if the mouse is considered above the button, false otherwise. + /// + private bool IsValidMousePosition() + { + return (_mousePosition.X >= 0.0) && + (_mousePosition.X <= ActualWidth) && + (_mousePosition.Y >= 0.0) && + (_mousePosition.Y <= ActualHeight); + } - _suspendStateChanges = false; - UpdateVisualState(); - } + protected bool GoToState(bool useTransitions, string stateName) + { + return VisualStateManager.GoToState(this, stateName, useTransitions); + } - /// - /// Responds to the MouseLeftButtonUp event. - /// - /// - /// The event data for the MouseLeftButtonUp event. - /// - protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) - { - base.OnMouseLeftButtonUp(e); - if (e.Handled) - { - return; - } - - _isMouseLeftButtonDown = false; - - if (!IsEnabled) - { - return; - } - - e.Handled = true; - if (!_isSpaceKeyDown && IsPressed) - { - OnClick(); - } - - if (!_isSpaceKeyDown) - { - ReleaseMouseCaptureInternal(); - IsPressed = false; - } - } + protected virtual void ChangeVisualState(bool useTransitions) + { + if (!IsEnabled) + { + GoToState(useTransitions, DisabledState); + } + else + { + GoToState(useTransitions, IsMouseOver ? MouseOverState : NormalState); + } + + if (IsFocused && IsEnabled) + { + GoToState(useTransitions, FocusedState); + } + else + { + GoToState(useTransitions, UnfocusedState); + } + } - /// - /// Responds to the MouseMove event. - /// - /// The event data for the MouseMove event. - protected override void OnMouseMove(MouseEventArgs e) - { - base.OnMouseMove(e); - _mousePosition = e.GetPosition(this); - - if (_isMouseLeftButtonDown && - IsEnabled && - _isMouseCaptured && - !_isSpaceKeyDown) - { - IsPressed = IsValidMousePosition(); - } - } + protected void UpdateVisualState(bool useTransitions = true) + { + if (!_suspendStateChanges) + { + ChangeVisualState(useTransitions); + } + } - /// - /// Determine if the mouse is above the button based on its last known - /// position. - /// - /// - /// True if the mouse is considered above the button, false otherwise. - /// - private bool IsValidMousePosition() - { - return (_mousePosition.X >= 0.0) && - (_mousePosition.X <= ActualWidth) && - (_mousePosition.Y >= 0.0) && - (_mousePosition.Y <= ActualHeight); - } + /// + /// Updates the control's layout to reflect the current IsChecked state. + /// + /// Whether to use transitions during the layout change. + protected virtual void ChangeCheckStates(bool useTransitions) + { + var state = IsChecked ? CheckedState : UncheckedState; + + if (IsDragging) + { + VisualStateManager.GoToState(this, DraggingState + state, useTransitions); + } + else + { + VisualStateManager.GoToState(this, state, useTransitions); + if (SwitchThumb != null) + { + VisualStateManager.GoToState(SwitchThumb, state, useTransitions); + } + } + + if (SwitchThumb == null || SwitchTrack == null) + { + return; + } + + var storyboard = new Storyboard(); + var duration = new Duration(useTransitions ? TimeSpan.FromMilliseconds(100) : TimeSpan.Zero); + var backgroundAnimation = new DoubleAnimation(); + var thumbAnimation = new DoubleAnimation(); + + backgroundAnimation.Duration = duration; + thumbAnimation.Duration = duration; + + double offset = IsChecked ? CheckedOffset : UncheckedOffset; + backgroundAnimation.To = offset; + thumbAnimation.To = offset; + + storyboard.Children.Add(backgroundAnimation); + storyboard.Children.Add(thumbAnimation); + + Storyboard.SetTarget(backgroundAnimation, SwitchTrack); + Storyboard.SetTarget(thumbAnimation, SwitchThumb); + + Storyboard.SetTargetProperty(backgroundAnimation, SlidePropertyPath); + Storyboard.SetTargetProperty(thumbAnimation, SlidePropertyPath); + + storyboard.Begin(); + } - protected bool GoToState(bool useTransitions, string stateName) - { - return VisualStateManager.GoToState(this, stateName, useTransitions); - } + #region ICommandSource Implementation + // Add a new command to the Command Property. + private void HookUpCommand(ICommand oldCommand, ICommand newCommand) + { + // If oldCommand is not null, then we need to remove the handlers. + if (oldCommand != null) + { + RemoveCommand(oldCommand, newCommand); + } + AddCommand(oldCommand, newCommand); + } - protected virtual void ChangeVisualState(bool useTransitions) - { - if (!IsEnabled) - { - GoToState(useTransitions, DisabledState); - } - else - { - GoToState(useTransitions, IsMouseOver ? MouseOverState : NormalState); - } - - if (IsFocused && IsEnabled) - { - GoToState(useTransitions, FocusedState); - } - else - { - GoToState(useTransitions, UnfocusedState); - } - } + // Remove an old command from the Command Property. + private void RemoveCommand(ICommand oldCommand, ICommand newCommand) + { + EventHandler handler = CanExecuteChanged; + oldCommand.CanExecuteChanged -= handler; + } - protected void UpdateVisualState(bool useTransitions = true) - { - if (!_suspendStateChanges) - { - ChangeVisualState(useTransitions); - } - } + // Add the command. + private void AddCommand(ICommand oldCommand, ICommand newCommand) + { + EventHandler handler = new EventHandler(CanExecuteChanged); + var canExecuteChangedHandler = handler; + if (newCommand != null) + { + newCommand.CanExecuteChanged += canExecuteChangedHandler; + } + } - /// - /// Updates the control's layout to reflect the current IsChecked state. - /// - /// Whether to use transitions during the layout change. - protected virtual void ChangeCheckStates(bool useTransitions) - { - var state = IsChecked ? CheckedState : UncheckedState; - - if (IsDragging) - { - VisualStateManager.GoToState(this, DraggingState + state, useTransitions); - } - else - { - VisualStateManager.GoToState(this, state, useTransitions); - if (SwitchThumb != null) - { - VisualStateManager.GoToState(SwitchThumb, state, useTransitions); - } - } - - if (SwitchThumb == null || SwitchTrack == null) - { - return; - } - - var storyboard = new Storyboard(); - var duration = new Duration(useTransitions ? TimeSpan.FromMilliseconds(100) : TimeSpan.Zero); - var backgroundAnimation = new DoubleAnimation(); - var thumbAnimation = new DoubleAnimation(); - - backgroundAnimation.Duration = duration; - thumbAnimation.Duration = duration; - - double offset = IsChecked ? CheckedOffset : UncheckedOffset; - backgroundAnimation.To = offset; - thumbAnimation.To = offset; - - storyboard.Children.Add(backgroundAnimation); - storyboard.Children.Add(thumbAnimation); - - Storyboard.SetTarget(backgroundAnimation, SwitchTrack); - Storyboard.SetTarget(thumbAnimation, SwitchThumb); - - Storyboard.SetTargetProperty(backgroundAnimation, SlidePropertyPath); - Storyboard.SetTargetProperty(thumbAnimation, SlidePropertyPath); - - storyboard.Begin(); - } - } + private void CanExecuteChanged(object sender, EventArgs e) + { + + if (this.Command != null) + { + RoutedCommand command = this.Command as RoutedCommand; + + // If a RoutedCommand. + if (command != null) + { + if (command.CanExecute(CommandParameter, CommandTarget)) + { + this.IsEnabled = true; + } + else + { + this.IsEnabled = false; + } + } + // If a not RoutedCommand. + else + { + if (Command.CanExecute(CommandParameter)) + { + this.IsEnabled = true; + } + else + { + this.IsEnabled = false; + } + } + } + } + #endregion + } } \ No newline at end of file diff --git a/WPF/Demo/Controls/RelayCommand.cs b/WPF/Demo/Controls/RelayCommand.cs new file mode 100644 index 0000000..3fd1248 --- /dev/null +++ b/WPF/Demo/Controls/RelayCommand.cs @@ -0,0 +1,34 @@ + +using System; +using System.Windows.Input; + +namespace Demo.Controls +{ + public class RelayCommand : ICommand + { + private Action execute; + private Func canExecute; + + public event EventHandler CanExecuteChanged + { + add { CommandManager.RequerySuggested += value; } + remove { CommandManager.RequerySuggested -= value; } + } + + public RelayCommand(Action execute, Func canExecute = null) + { + this.execute = execute; + this.canExecute = canExecute; + } + + public bool CanExecute(object parameter) + { + return this.canExecute == null || this.canExecute(parameter); + } + + public void Execute(object parameter) + { + this.execute(parameter); + } + } +} \ No newline at end of file diff --git a/WPF/Demo/Demo.csproj b/WPF/Demo/Demo.csproj index 971193f..8b0e580 100644 --- a/WPF/Demo/Demo.csproj +++ b/WPF/Demo/Demo.csproj @@ -115,6 +115,7 @@ Controls\VerticalToggleSwitch.cs + Basics.xaml diff --git a/WPF/Demo/DemoViewModel.cs b/WPF/Demo/DemoViewModel.cs index f01bede..c52e29b 100644 --- a/WPF/Demo/DemoViewModel.cs +++ b/WPF/Demo/DemoViewModel.cs @@ -1,48 +1,62 @@ -using System; +using Demo.Controls; +using System; using System.ComponentModel; +using System.Windows; +using System.Windows.Input; using System.Windows.Threading; namespace Demo { - public class DemoViewModel : INotifyPropertyChanged - { - private readonly DispatcherTimer _restartEventTimer = new DispatcherTimer(); + public class DemoViewModel : INotifyPropertyChanged + { + private RelayCommand _test_command; + private readonly DispatcherTimer _restartEventTimer = new DispatcherTimer(); - public DemoViewModel() - { - _restartEventTimer.Interval = TimeSpan.FromSeconds(1.5); - _restartEventTimer.Tick += delegate { _restartEventTimer.Stop(); RestartToggleChecked = false; }; - } + public ICommand TestCommand { get { return _test_command; } } + public DemoViewModel() + { + _restartEventTimer.Interval = TimeSpan.FromSeconds(1.5); + _restartEventTimer.Tick += delegate { _restartEventTimer.Stop(); RestartToggleChecked = false; }; + _test_command = new RelayCommand(ExecuteTest); + } - private bool _restartToggleChecked; - public bool RestartToggleChecked - { - get - { - return _restartToggleChecked; - } - set - { - if (_restartToggleChecked != value) - { - _restartToggleChecked = value; - InvokePropertyChanged("RestartToggleChecked"); + private bool _restartToggleChecked; + public bool RestartToggleChecked + { + get + { + return _restartToggleChecked; + } + set + { + if (_restartToggleChecked != value) + { + _restartToggleChecked = value; + InvokePropertyChanged("RestartToggleChecked"); - if (_restartToggleChecked) - { - _restartEventTimer.Start(); - } - } - } - } + if (_restartToggleChecked) + { + _restartEventTimer.Start(); + } + } + } + } - public event PropertyChangedEventHandler PropertyChanged; - public void InvokePropertyChanged(string propertyName) - { - if (PropertyChanged != null) - { - PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); - } - } - } + public event PropertyChangedEventHandler PropertyChanged; + public void InvokePropertyChanged(string propertyName) + { + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + public void ExecuteTest(object sender) + { + var message = "Command Executed." + Environment.NewLine; + message += "TextBlock Content : " + Environment.NewLine; + message += sender.ToString(); + MessageBox.Show(message, "Information", MessageBoxButton.OK, MessageBoxImage.Information); + } + } } diff --git a/WPF/Demo/Views/Basics.xaml b/WPF/Demo/Views/Basics.xaml index 0d16577..919d641 100644 --- a/WPF/Demo/Views/Basics.xaml +++ b/WPF/Demo/Views/Basics.xaml @@ -17,21 +17,25 @@ - + - + HorizontalAlignment="Left" + Command="{Binding TestCommand}" + CommandParameter="{Binding Path=Text, ElementName=TextBlock1}" /> + + HorizontalAlignment="Left" + Command="{Binding TestCommand}" + CommandParameter="{Binding Path=Text, ElementName=TextBlock2}"> @@ -42,7 +46,7 @@ - + + Grid.Row="2" + Command="{Binding TestCommand}" + CommandParameter="{Binding Path=Text, ElementName=TextBlock3}"/>