diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ButtonSpinner/ButtonSpinner.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ButtonSpinner/ButtonSpinner.cs new file mode 100644 index 00000000..467f6c85 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ButtonSpinner/ButtonSpinner.cs @@ -0,0 +1,192 @@ +using System; +using System.Windows; +using System.Windows.Input; +using System.Windows.Markup; +using System.Windows.Controls.Primitives; +using Microsoft.Windows.Controls.Primitives; + +namespace Microsoft.Windows.Controls +{ + /// + /// Represents a spinner control that includes two Buttons. + /// + [ContentProperty("Content")] + public class ButtonSpinner : Spinner + { + #region Properties + + #region Content + + /// + /// Identifies the Content dependency property. + /// + public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(object), typeof(ButtonSpinner), new PropertyMetadata(null, OnContentPropertyChanged)); + public object Content + { + get { return GetValue(ContentProperty) as object; } + set { SetValue(ContentProperty, value); } + } + + /// + /// ContentProperty property changed handler. + /// + /// ButtonSpinner that changed its Content. + /// Event arguments. + private static void OnContentPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ButtonSpinner source = d as ButtonSpinner; + source.OnContentChanged(e.OldValue, e.NewValue); + } + + #endregion //Content + + private ButtonBase _increaseButton; + /// + /// Gets or sets the IncreaseButton template part. + /// + private ButtonBase IncreaseButton + { + get { return _increaseButton; } + set + { + if (_increaseButton != null) + { + _increaseButton.Click -= OnButtonClick; + } + + _increaseButton = value; + + if (_increaseButton != null) + { + _increaseButton.Click += OnButtonClick; + } + } + } + + + private ButtonBase _decreaseButton; + /// + /// Gets or sets the DecreaseButton template part. + /// + private ButtonBase DecreaseButton + { + get { return _decreaseButton; } + set + { + if (_decreaseButton != null) + { + _decreaseButton.Click -= OnButtonClick; + } + + _decreaseButton = value; + + if (_decreaseButton != null) + { + _decreaseButton.Click += OnButtonClick; + } + } + } + + #endregion //Properties + + #region Constructors + + static ButtonSpinner() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(ButtonSpinner), new FrameworkPropertyMetadata(typeof(ButtonSpinner))); + } + + #endregion //Constructors + + #region Base Class Overrides + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + IncreaseButton = GetTemplateChild("IncreaseButton") as ButtonBase; + DecreaseButton = GetTemplateChild("DecreaseButton") as ButtonBase; + + SetButtonUsage(); + } + + #endregion //Base Class Overrides + + /// + /// Occurs when the Content property value changed. + /// + /// The old value of the Content property. + /// The new value of the Content property. + protected virtual void OnContentChanged(object oldValue, object newValue) { } + + /// + /// Handle click event of IncreaseButton and DecreaseButton template parts, + /// translating Click to appropriate Spin event. + /// + /// Event sender, should be either IncreaseButton or DecreaseButton template part. + /// Event args. + private void OnButtonClick(object sender, RoutedEventArgs e) + { + SpinDirection direction = sender == IncreaseButton ? SpinDirection.Increase : SpinDirection.Decrease; + OnSpin(new SpinEventArgs(direction)); + } + + /// + /// Cancel LeftMouseButtonUp events originating from a button that has + /// been changed to disabled. + /// + /// The data for the event. + protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) + { + base.OnMouseLeftButtonUp(e); + + Point mousePosition; + if (IncreaseButton != null && IncreaseButton.IsEnabled == false) + { + mousePosition = e.GetPosition(IncreaseButton); + if (mousePosition.X > 0 && mousePosition.X < IncreaseButton.ActualWidth && + mousePosition.Y > 0 && mousePosition.Y < IncreaseButton.ActualHeight) + { + e.Handled = true; + } + } + + if (DecreaseButton != null && DecreaseButton.IsEnabled == false) + { + mousePosition = e.GetPosition(DecreaseButton); + if (mousePosition.X > 0 && mousePosition.X < DecreaseButton.ActualWidth && + mousePosition.Y > 0 && mousePosition.Y < DecreaseButton.ActualHeight) + { + e.Handled = true; + } + } + } + + /// + /// Called when valid spin direction changed. + /// + /// The old value. + /// The new value. + protected override void OnValidSpinDirectionChanged(ValidSpinDirections oldValue, ValidSpinDirections newValue) + { + SetButtonUsage(); + } + + /// + /// Disables or enables the buttons based on the valid spin direction. + /// + private void SetButtonUsage() + { + // buttonspinner adds buttons that spin, so disable accordingly. + if (IncreaseButton != null) + { + IncreaseButton.IsEnabled = ((ValidSpinDirection & ValidSpinDirections.Increase) == ValidSpinDirections.Increase); + } + + if (DecreaseButton != null) + { + DecreaseButton.IsEnabled = ((ValidSpinDirection & ValidSpinDirections.Decrease) == ValidSpinDirections.Decrease); + } + } + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/SpinDirection.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/SpinDirection.cs new file mode 100644 index 00000000..a5e58cc3 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/SpinDirection.cs @@ -0,0 +1,21 @@ +using System; + +namespace Microsoft.Windows.Controls.Primitives +{ + /// + /// Represents spin directions that could be initiated by the end-user. + /// + /// Preview + public enum SpinDirection + { + /// + /// Represents a spin initiated by the end-user in order to Increase a value. + /// + Increase = 0, + + /// + /// Represents a spin initiated by the end-user in order to Decrease a value. + /// + Decrease = 1 + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/SpinEventArgs.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/SpinEventArgs.cs new file mode 100644 index 00000000..5750f13f --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/SpinEventArgs.cs @@ -0,0 +1,28 @@ +using System; +using System.Windows; + +namespace Microsoft.Windows.Controls.Primitives +{ + /// + /// Provides data for the Spinner.Spin event. + /// + /// Preview + public class SpinEventArgs : RoutedEventArgs + { + /// + /// Gets the SpinDirection for the spin that has been initiated by the + /// end-user. + /// + public SpinDirection Direction { get; private set; } + + /// + /// Initializes a new instance of the SpinEventArgs class. + /// + /// Spin direction. + public SpinEventArgs(SpinDirection direction) + : base() + { + Direction = direction; + } + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/Spinner.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/Spinner.cs new file mode 100644 index 00000000..cb169de9 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/Spinner.cs @@ -0,0 +1,77 @@ +using System; +using System.Windows.Controls; +using System.Windows; + +namespace Microsoft.Windows.Controls.Primitives +{ + /// + /// Base class for controls that represents controls that can spin. + /// + public abstract class Spinner : Control + { + #region Properties + + /// + /// Identifies the ValidSpinDirection dependency property. + /// + public static readonly DependencyProperty ValidSpinDirectionProperty = DependencyProperty.Register("ValidSpinDirection", typeof(ValidSpinDirections), typeof(Spinner), new PropertyMetadata(ValidSpinDirections.Increase | ValidSpinDirections.Decrease, OnValidSpinDirectionPropertyChanged)); + public ValidSpinDirections ValidSpinDirection + { + get { return (ValidSpinDirections)GetValue(ValidSpinDirectionProperty); } + set { SetValue(ValidSpinDirectionProperty, value); } + } + + /// + /// ValidSpinDirectionProperty property changed handler. + /// + /// ButtonSpinner that changed its ValidSpinDirection. + /// Event arguments. + private static void OnValidSpinDirectionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + Spinner source = (Spinner)d; + ValidSpinDirections oldvalue = (ValidSpinDirections)e.OldValue; + ValidSpinDirections newvalue = (ValidSpinDirections)e.NewValue; + source.OnValidSpinDirectionChanged(oldvalue, newvalue); + } + + #endregion //Properties + + /// + /// Occurs when spinning is initiated by the end-user. + /// + public event EventHandler Spin; + + /// + /// Initializes a new instance of the Spinner class. + /// + protected Spinner() { } + + /// + /// Raises the OnSpin event when spinning is initiated by the end-user. + /// + /// Spin event args. + protected virtual void OnSpin(SpinEventArgs e) + { + ValidSpinDirections valid = e.Direction == SpinDirection.Increase ? ValidSpinDirections.Increase : ValidSpinDirections.Decrease; + + if ((ValidSpinDirection & valid) != valid) + { + // spin is not allowed. + throw new InvalidOperationException("Spin action is not valid at this moment."); + } + + EventHandler handler = Spin; + if (handler != null) + { + handler(this, e); + } + } + + /// + /// Called when valid spin direction changed. + /// + /// The old value. + /// The new value. + protected virtual void OnValidSpinDirectionChanged(ValidSpinDirections oldValue, ValidSpinDirections newValue) { } + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/ValidSpinDirections.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/ValidSpinDirections.cs new file mode 100644 index 00000000..4099bc25 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/ValidSpinDirections.cs @@ -0,0 +1,26 @@ +using System; + +namespace Microsoft.Windows.Controls.Primitives +{ + /// + /// Represents spin directions that are valid. + /// + [Flags] + public enum ValidSpinDirections + { + /// + /// Can not increase nor decrease. + /// + None = 0, + + /// + /// Can increase. + /// + Increase = 1, + + /// + /// Can decrease. + /// + Decrease = 2 + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml index c9aa9d50..5c8adc47 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml @@ -926,4 +926,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj index feb35caf..627f466e 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj @@ -64,6 +64,7 @@ + @@ -71,6 +72,10 @@ + + + + Code