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