From 9d85504a12a1ee9be569553d46c8423d0ce69796 Mon Sep 17 00:00:00 2001 From: brianlagunas_cp Date: Wed, 30 Mar 2011 23:21:41 +0000 Subject: [PATCH] In order to reliably support the different numeric data types, I need to create a specific control for each data type. So instead of copying and pasting I am going to try to create a generic base class that has most of the logic in it. This will make the NumericUpDown control obsolete and it will be removed from the toolkit. The new controls will be DecimalUpDown, DoubleUpDown, and IntegerUpDown. --- .../Core/Primitives/InputBase.cs | 13 +- .../Core/Primitives/UpDownBase.cs | 264 ++++++++++++++++++ 2 files changed, 271 insertions(+), 6 deletions(-) diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/InputBase.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/InputBase.cs index f3ec5fdf..0b813db4 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/InputBase.cs +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/InputBase.cs @@ -21,23 +21,24 @@ namespace Microsoft.Windows.Controls.Primitives #region Text - public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(InputBase), new PropertyMetadata(default(String), OnTextPropertyChanged)); + public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(InputBase), new UIPropertyMetadata(default(String), OnTextChanged)); public string Text { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } - private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + private static void OnTextChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { - InputBase input = (InputBase)d; - input.OnTextChanged((string)e.OldValue, (string)e.NewValue); + InputBase inputBase = o as InputBase; + if (inputBase != null) + inputBase.OnTextChanged((string)e.OldValue, (string)e.NewValue); } - protected virtual void OnTextChanged(string previousValue, string currentValue) + protected virtual void OnTextChanged(string oldValue, string newValue) { - } + } #endregion //Text diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/UpDownBase.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/UpDownBase.cs index ae415f7b..3f4c1a5e 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/UpDownBase.cs +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/UpDownBase.cs @@ -186,4 +186,268 @@ namespace Microsoft.Windows.Controls.Primitives #endregion //Methods } + + /// + /// This is going to be the new UpDownBase class. In order to reliably support the different numeric data types, I need to create a specific control for each data type. + /// So instead of copying and pasting I am going to try to create a generic base class that has most of the logic in it. This will make the NumericUpDown control obsolete + /// and it will be removed from the toolkit. The new controls will be DecimalUpDown, DoubleUpDown, and IntegerUpDown. + /// + /// + public abstract class UpDownBase : InputBase + { + #region Members + + /// + /// Name constant for Text template part. + /// + internal const string ElementTextName = "TextBox"; + + /// + /// Name constant for Spinner template part. + /// + internal const string ElementSpinnerName = "Spinner"; + + /// + /// Flags if the Text and Value properties are in the process of being sync'd + /// + private bool _isSyncingTextAndValueProperties; + + #endregion //Members + + #region Properties + + protected TextBox TextBox { get; private set; } + internal Spinner Spinner { get; private set; } + + #region AllowSpin + + public static readonly DependencyProperty AllowSpinProperty = DependencyProperty.Register("AllowSpin", typeof(bool), typeof(UpDownBase), new UIPropertyMetadata(true)); + public bool AllowSpin + { + get { return (bool)GetValue(AllowSpinProperty); } + set { SetValue(AllowSpinProperty, value); } + } + + #endregion //AllowSpin + + #region ShowButtonSpinner + + public static readonly DependencyProperty ShowButtonSpinnerProperty = DependencyProperty.Register("ShowButtonSpinner", typeof(bool), typeof(UpDownBase), new UIPropertyMetadata(true)); + public bool ShowButtonSpinner + { + get { return (bool)GetValue(ShowButtonSpinnerProperty); } + set { SetValue(ShowButtonSpinnerProperty, value); } + } + + #endregion //ShowButtonSpinner + + #region Value + + public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(T), typeof(UpDownBase), new UIPropertyMetadata(default(T), OnValueChanged, OnCoerceValue)); + public T Value + { + get { return (T)GetValue(ValueProperty); } + set { SetValue(ValueProperty, value); } + } + + private static object OnCoerceValue(DependencyObject o, object value) + { + UpDownBase upDownBase = o as UpDownBase; + if (upDownBase != null) + return upDownBase.OnCoerceValue((T)value); + else + return value; + } + + protected virtual T OnCoerceValue(T value) + { + return value; + } + + private static void OnValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + UpDownBase upDownBase = o as UpDownBase; + if (upDownBase != null) + upDownBase.OnValueChanged((T)e.OldValue, (T)e.NewValue); + } + + protected virtual void OnValueChanged(T oldValue, T newValue) + { + SyncTextAndValueProperties(NumericUpDown.ValueProperty, newValue); + + RoutedPropertyChangedEventArgs args = new RoutedPropertyChangedEventArgs(oldValue, newValue); + args.RoutedEvent = NumericUpDown.ValueChangedEvent; + RaiseEvent(args); + } + + #endregion //Value + + #endregion //Properties + + #region Constructors + + internal UpDownBase() { } + + #endregion //Constructors + + #region Base Class Overrides + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + TextBox = GetTemplateChild(ElementTextName) as TextBox; + Spinner = GetTemplateChild(ElementSpinnerName) as Spinner; + Spinner.Spin += OnSpinnerSpin; + } + + protected override void OnPreviewKeyDown(KeyEventArgs e) + { + switch (e.Key) + { + case Key.Up: + { + if (AllowSpin) + DoIncrement(); + e.Handled = true; + break; + } + case Key.Down: + { + if (AllowSpin) + DoDecrement(); + e.Handled = true; + break; + } + //case Key.Enter: + // { + // if (IsEditable) + // SyncTextAndValueProperties(UpDownBase.TextProperty, TextBox.Text); + // break; + // } + } + } + + protected override void OnMouseWheel(MouseWheelEventArgs e) + { + base.OnMouseWheel(e); + + if (!e.Handled && AllowSpin) + { + if (e.Delta < 0) + { + DoDecrement(); + } + else if (0 < e.Delta) + { + DoIncrement(); + } + + e.Handled = true; + } + } + + protected override void OnTextChanged(string oldValue, string newValue) + { + SyncTextAndValueProperties(InputBase.TextProperty, newValue); + } + + #endregion //Base Class Overrides + + #region Event Handlers + + private void OnSpinnerSpin(object sender, SpinEventArgs e) + { + if (AllowSpin) + OnSpin(e); + } + + #endregion //Event Handlers + + #region Events + + public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler), typeof(NumericUpDown)); + public event RoutedPropertyChangedEventHandler ValueChanged + { + add { AddHandler(ValueChangedEvent, value); } + remove { RemoveHandler(ValueChangedEvent, value); } + } + + #endregion //Events + + #region Methods + + protected virtual void OnSpin(SpinEventArgs e) + { + if (e == null) + throw new ArgumentNullException("e"); + + if (e.Direction == SpinDirection.Increase) + DoIncrement(); + else + DoDecrement(); + } + + /// + /// Performs an increment if conditions allow it. + /// + private void DoDecrement() + { + if (Spinner == null || (Spinner.ValidSpinDirection & ValidSpinDirections.Decrease) == ValidSpinDirections.Decrease) + { + OnDecrement(); + } + } + + /// + /// Performs a decrement if conditions allow it. + /// + private void DoIncrement() + { + if (Spinner == null || (Spinner.ValidSpinDirection & ValidSpinDirections.Increase) == ValidSpinDirections.Increase) + { + OnIncrement(); + } + } + + private void SyncTextAndValueProperties(DependencyProperty p, object newValue) + { + //prevents recursive syncing properties + if (_isSyncingTextAndValueProperties) + return; + + _isSyncingTextAndValueProperties = true; + + //this only occures when the user typed in the value + if (InputBase.TextProperty == p) + { + string text = newValue == null ? String.Empty : newValue.ToString(); + SetValue(UpDownBase.ValueProperty, ConvertTextToValue(text)); + } + + SetValue(InputBase.TextProperty, ConvertValueToText(newValue)); + + _isSyncingTextAndValueProperties = false; + } + + #region Abstract + + /// + /// Called by OnSpin when the spin direction is SpinDirection.Increase. + /// + protected abstract void OnIncrement(); + + /// + /// Called by OnSpin when the spin direction is SpinDirection.Descrease. + /// + protected abstract void OnDecrement(); + + protected abstract T ConvertTextToValue(string text); + + protected abstract string ConvertValueToText(object value); + + #endregion //Abstract + + #endregion //Methods + } }