diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/ChildWindow.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/ChildWindow.cs index 8a44695d..7f4314ee 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/ChildWindow.cs +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/ChildWindow.cs @@ -5,6 +5,7 @@ using System.Windows.Input; using System.Windows.Media; using System.Windows.Controls.Primitives; using System.ComponentModel; +using System.Windows.Shapes; namespace Microsoft.Windows.Controls { @@ -14,13 +15,16 @@ namespace Microsoft.Windows.Controls { #region Private Members + private Grid _root; private TranslateTransform _moveTransform = new TranslateTransform(); private bool _startupPositionInitialized; private bool _isMouseCaptured; private Point _clickPoint; private Point _oldPosition; private Border _dragWidget; - private FrameworkElement _parent; + private FrameworkElement _parentContainer; + private Rectangle _modalLayer = new Rectangle(); + private Canvas _modalLayerPanel = new Canvas(); #endregion //Private Members @@ -33,15 +37,8 @@ namespace Microsoft.Windows.Controls public ChildWindow() { - LayoutUpdated += (o, e) => - { - //we only want to set the start position if this is the first time the control has bee initialized - if (!_startupPositionInitialized) - { - SetStartupPosition(); - _startupPositionInitialized = true; - } - }; + _modalLayer.Fill = new SolidColorBrush(Colors.Gray); + _modalLayer.Opacity = 0.5; } #endregion //Constructors @@ -64,29 +61,34 @@ namespace Microsoft.Windows.Controls if (CloseButton != null) CloseButton.Click += (o, e) => Close(); - Overlay = GetTemplateChild("PART_Overlay") as Panel; + //Overlay = GetTemplateChild("PART_Overlay") as Panel; WindowRoot = GetTemplateChild("PART_WindowRoot") as Grid; WindowRoot.RenderTransform = _moveTransform; //TODO: move somewhere else - _parent = VisualTreeHelper.GetParent(this) as FrameworkElement; - _parent.SizeChanged += (o, ea) => + _parentContainer = VisualTreeHelper.GetParent(this) as FrameworkElement; + _parentContainer.LayoutUpdated += ParentContainer_LayoutUpdated; + _parentContainer.SizeChanged += (o, ea) => { - Overlay.Height = ea.NewSize.Height; - Overlay.Width = ea.NewSize.Width; + _modalLayer.Height = ea.NewSize.Height; + _modalLayer.Width = ea.NewSize.Width; }; + _root = GetTemplateChild("Root") as Grid; + _root.Children.Add(_modalLayerPanel); + ChangeVisualState(); } + + #endregion //Base Class Overrides #region Properties #region Internal Properties - internal Panel Overlay { get; private set; } internal Grid WindowRoot { get; private set; } internal Thumb DragWidget { get; private set; } internal Button MinimizeButton { get; private set; } @@ -132,13 +134,34 @@ namespace Microsoft.Windows.Controls set { SetValue(IconSourceProperty, value); } } - public static readonly DependencyProperty IsModalProperty = DependencyProperty.Register("IsModal", typeof(bool), typeof(ChildWindow), new UIPropertyMetadata(true)); + public static readonly DependencyProperty IsModalProperty = DependencyProperty.Register("IsModal", typeof(bool), typeof(ChildWindow), new UIPropertyMetadata(false, new PropertyChangedCallback(OnIsModalPropertyChanged))); public bool IsModal { get { return (bool)GetValue(IsModalProperty); } set { SetValue(IsModalProperty, value); } } + private static void OnIsModalPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ChildWindow childWindow = (ChildWindow)d; + if ((bool)e.NewValue) + childWindow.ShowModalLayer(); + else + childWindow.HideModalLayer(); + } + + private void ShowModalLayer() + { + + _modalLayerPanel.Children.Add(_modalLayer); + BringToFront(); + } + + private void HideModalLayer() + { + + } + #region Left public static readonly DependencyProperty LeftProperty = DependencyProperty.Register("Left", typeof(double), typeof(ChildWindow), new PropertyMetadata(0.0, new PropertyChangedCallback(OnLeftPropertyChanged))); @@ -301,6 +324,19 @@ namespace Microsoft.Windows.Controls } } + private void ParentContainer_LayoutUpdated(object sender, EventArgs e) + { + if (DesignerProperties.GetIsInDesignMode(this)) + return; + + //we only want to set the start position if this is the first time the control has bee initialized + if (!_startupPositionInitialized) + { + SetStartupPosition(); + _startupPositionInitialized = true; + } + } + #endregion //Event Handlers #region Methods @@ -309,16 +345,16 @@ namespace Microsoft.Windows.Controls private double GetRestrictedLeft() { - if (_parent != null) + if (_parentContainer != null) { if (Left < 0) { return 0; } - if (Left + WindowRoot.ActualWidth > _parent.ActualWidth) + if (Left + WindowRoot.ActualWidth > _parentContainer.ActualWidth) { - return _parent.ActualWidth - WindowRoot.ActualWidth; + return _parentContainer.ActualWidth - WindowRoot.ActualWidth; } } @@ -327,16 +363,16 @@ namespace Microsoft.Windows.Controls private double GetRestrictedTop() { - if (_parent != null) + if (_parentContainer != null) { if (Top < 0) { return 0; } - if (Top + WindowRoot.ActualHeight > _parent.ActualHeight) + if (Top + WindowRoot.ActualHeight > _parentContainer.ActualHeight) { - return _parent.ActualHeight - WindowRoot.ActualHeight; + return _parentContainer.ActualHeight - WindowRoot.ActualHeight; } } @@ -383,14 +419,14 @@ namespace Microsoft.Windows.Controls private void ExecuteOpen() { _dialogResult = null; //reset the dialogResult to null each time the window is opened - SetZIndex(); + SetZIndex(); //TODO: replace with BringToFront } private void SetZIndex() { - if (_parent != null) + if (_parentContainer != null) { - int parentIndex = (int)_parent.GetValue(Canvas.ZIndexProperty); + int parentIndex = (int)_parentContainer.GetValue(Canvas.ZIndexProperty); this.SetValue(Canvas.ZIndexProperty, ++parentIndex); } else @@ -399,19 +435,32 @@ namespace Microsoft.Windows.Controls } } + private void BringToFront() + { + int zIndex = 0; + + this.SetValue(Canvas.ZIndexProperty, 1); + + Canvas.SetZIndex(this, zIndex += 99); + + //if modal + + } + private void SetStartupPosition() { CenterChildWindow(); + BringToFront(); } private void CenterChildWindow() { _moveTransform.X = _moveTransform.Y = 0; - if (_parent != null) + if (_parentContainer != null) { - Left = (_parent.ActualWidth - WindowRoot.ActualWidth) / 2.0; - Top = (_parent.ActualHeight - WindowRoot.ActualHeight) / 2.0; + Left = (_parentContainer.ActualWidth - WindowRoot.ActualWidth) / 2.0; + Top = (_parentContainer.ActualHeight - WindowRoot.ActualHeight) / 2.0; } } diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/InputBase.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/InputBase.cs new file mode 100644 index 00000000..9b19c0ff --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/InputBase.cs @@ -0,0 +1,159 @@ +using System; +using System.Windows.Controls; +using System.Windows; + +namespace Microsoft.Windows.Controls.Primitives +{ + public abstract class InputBase : Control + { + #region Members + + /// + /// Flags if the Text and Value properties are in the process of being sync'd + /// + private bool _isSyncingTextAndValueProperties; + private bool _isInitialized; + + #endregion //Members + + #region Properties + + public virtual object PreviousValue { get; internal set; } + + #region DisplayText + + public static readonly DependencyProperty DisplayTextProperty = DependencyProperty.Register("DisplayText", typeof(string), typeof(InputBase), new FrameworkPropertyMetadata(default(String), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnDisplayTextPropertyChanged)); + public string DisplayText + { + get { return (string)this.GetValue(DisplayTextProperty); } + set { this.SetValue(DisplayTextProperty, value); } + } + + private static void OnDisplayTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + InputBase input = (InputBase)d; + input.OnDisplayTextChanged((string)e.OldValue, (string)e.NewValue); + if (input._isInitialized) + input.SyncTextAndValueProperties(e.Property, e.NewValue); + } + + protected virtual void OnDisplayTextChanged(string previousValue, string currentValue) + { + + } + + #endregion //DisplayText + + #region IsEditable + + public static readonly DependencyProperty IsEditableProperty = DependencyProperty.Register("IsEditable", typeof(bool), typeof(InputBase), new PropertyMetadata(true)); + public bool IsEditable + { + get { return (bool)GetValue(IsEditableProperty); } + set { SetValue(IsEditableProperty, value); } + } + + #endregion //IsEditable + + #region Value + + public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(InputBase), new FrameworkPropertyMetadata(default(object), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValuePropertyChanged)); + public virtual object Value + { + get { return (object)GetValue(ValueProperty); } + set { SetValue(ValueProperty, value); } + } + + private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + InputBase input = (InputBase)d; + + if (e.OldValue != e.NewValue) + { + input.PreviousValue = e.OldValue; + input.OnValueChanged(e.OldValue, e.NewValue); + + if (input._isInitialized) + input.SyncTextAndValueProperties(e.Property, e.NewValue); + } + } + + protected virtual void OnValueChanged(object oldValue, object newValue) + { + + } + + #endregion //Value + + #region ValueType + + public static readonly DependencyProperty ValueTypeProperty = DependencyProperty.Register("ValueType", typeof(Type), typeof(InputBase), new FrameworkPropertyMetadata(typeof(String), FrameworkPropertyMetadataOptions.None, new PropertyChangedCallback(OnValueTypePropertyChanged))); + public Type ValueType + { + get { return (Type)GetValue(ValueTypeProperty); } + set { SetValue(ValueTypeProperty, value); } + } + + private static void OnValueTypePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + InputBase input = (InputBase)d; + input.OnValueTypeChanged((Type)e.OldValue, (Type)e.NewValue); + } + + protected virtual void OnValueTypeChanged(Type oldValue, Type newType) + { + if (_isInitialized) + SyncTextAndValueProperties(DisplayTextProperty, DisplayText); + } + + #endregion //ValueType + + #endregion //Properties + + #region Base Class Overrides + + protected override void OnInitialized(EventArgs e) + { + base.OnInitialized(e); + + if (!_isInitialized) + { + _isInitialized = true; + SyncTextAndValueProperties(ValueProperty, Value); + } + } + + #endregion //Base Class Overrides + + #region Methods + + protected 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.DisplayTextProperty == p) + { + SetValue(InputBase.ValueProperty, ConvertTextToValue(newValue.ToString())); + } + + SetValue(InputBase.DisplayTextProperty, ConvertValueToText(newValue)); + + _isSyncingTextAndValueProperties = false; + } + + #endregion //Methods + + #region Abstract + + protected abstract object ConvertTextToValue(string text); + + protected abstract string ConvertValueToText(object value); + + #endregion //Abstract + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/UpDownBase.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/UpDownBase.cs new file mode 100644 index 00000000..b0d0fe4b --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/UpDownBase.cs @@ -0,0 +1,162 @@ +using System; +using System.Windows.Controls; +using Microsoft.Windows.Controls.Primitives; +using System.Windows.Input; + +namespace Microsoft.Windows.Controls.Primitives +{ + 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"; + + #endregion //Members + + #region Properties + + protected TextBox TextBox { get; private set; } + + private Spinner _spinner; + internal Spinner Spinner + { + get { return _spinner; } + private set + { + _spinner = value; + _spinner.Spin += OnSpinnerSpin; + } + } + + #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; + } + + protected override void OnPreviewKeyDown(KeyEventArgs e) + { + switch (e.Key) + { + case Key.Up: + { + DoIncrement(); + e.Handled = true; + break; + } + case Key.Down: + { + DoDecrement(); + e.Handled = true; + break; + } + case Key.Enter: + { + SyncTextAndValueProperties(InputBase.DisplayTextProperty, TextBox.Text); + break; + } + } + } + + protected override void OnMouseWheel(MouseWheelEventArgs e) + { + base.OnMouseWheel(e); + + if (!e.Handled) + { + if (e.Delta < 0) + { + DoDecrement(); + } + else if (0 < e.Delta) + { + DoIncrement(); + } + + e.Handled = true; + } + } + + #endregion //Base Class Overrides + + #region Event Handlers + + private void OnSpinnerSpin(object sender, SpinEventArgs e) + { + OnSpin(e); + } + + #endregion //Event Handlers + + #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(); + } + } + + #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(); + + #endregion //Abstract + + #endregion //Methods + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MaskedTextBox/MaskedTextBox.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MaskedTextBox/MaskedTextBox.cs new file mode 100644 index 00000000..6026db0f --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MaskedTextBox/MaskedTextBox.cs @@ -0,0 +1,255 @@ +using System; +using System.Windows.Controls; +using System.Windows; +using System.Windows.Input; +using System.ComponentModel; +using Microsoft.Windows.Controls.Primitives; + +namespace Microsoft.Windows.Controls +{ + + public class MaskedTextBox : InputBase + { + #region Properties + + protected MaskedTextProvider MaskProvider { get; set; } + private TextBox TextBox { get; set; } + + #region IncludePrompt + + public static readonly DependencyProperty IncludePromptProperty = DependencyProperty.Register("IncludePrompt", typeof(bool), typeof(MaskedTextBox), new UIPropertyMetadata(false, OnIncludePromptPropertyChanged)); + public bool IncludePrompt + { + get { return (bool)GetValue(IncludePromptProperty); } + set { SetValue(IncludePromptProperty, value); } + } + + private static void OnIncludePromptPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + MaskedTextBox maskedTextBox = o as MaskedTextBox; + if (maskedTextBox != null) + maskedTextBox.OnIncludePromptChanged((bool)e.OldValue, (bool)e.NewValue); + } + + protected virtual void OnIncludePromptChanged(bool oldValue, bool newValue) + { + ResolveMaskProvider(Mask); + } + + #endregion //IncludePrompt + + #region IncludeLiterals + + public static readonly DependencyProperty IncludeLiteralsProperty = DependencyProperty.Register("IncludeLiterals", typeof(bool), typeof(MaskedTextBox), new UIPropertyMetadata(true, OnIncludeLiteralsPropertyChanged)); + public bool IncludeLiterals + { + get { return (bool)GetValue(IncludeLiteralsProperty); } + set { SetValue(IncludeLiteralsProperty, value); } + } + + private static void OnIncludeLiteralsPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + MaskedTextBox maskedTextBox = o as MaskedTextBox; + if (maskedTextBox != null) + maskedTextBox.OnIncludeLiteralsChanged((bool)e.OldValue, (bool)e.NewValue); + } + + protected virtual void OnIncludeLiteralsChanged(bool oldValue, bool newValue) + { + ResolveMaskProvider(Mask); + } + + #endregion //IncludeLiterals + + #region Mask + + public static readonly DependencyProperty MaskProperty = DependencyProperty.Register("Mask", typeof(string), typeof(MaskedTextBox), new UIPropertyMetadata(default(String), OnMaskPropertyChanged)); + public string Mask + { + get { return (string)GetValue(MaskProperty); } + set { SetValue(MaskProperty, value); } + } + + private static void OnMaskPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + MaskedTextBox maskedTextBox = o as MaskedTextBox; + if (maskedTextBox != null) + maskedTextBox.OnMaskChanged((string)e.OldValue, (string)e.NewValue); + } + + protected virtual void OnMaskChanged(string oldValue, string newValue) + { + ResolveMaskProvider(newValue); + UpdateText(MaskProvider, 0); + } + + #endregion //Mask + + #endregion //Properties + + #region Constructors + + static MaskedTextBox() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(MaskedTextBox), new FrameworkPropertyMetadata(typeof(MaskedTextBox))); + } + + #endregion //Constructors + + #region Overrides + + public override void OnApplyTemplate() + { + TextBox = GetTemplateChild("TextBox") as TextBox; + TextBox.PreviewTextInput += TextBox_PreviewTextInput; + TextBox.PreviewKeyDown += TextBox_PreviewKeyDown; + } + + protected override object ConvertTextToValue(string text) + { + object convertedValue = null; + + Type dataType = ValueType; + + string valueToConvert = MaskProvider.ToString(); + + if (valueToConvert.GetType() == dataType || dataType.IsInstanceOfType(valueToConvert)) + { + convertedValue = valueToConvert; + } + else if (String.IsNullOrWhiteSpace(valueToConvert)) + { + convertedValue = Activator.CreateInstance(dataType); + } + else if (null == convertedValue && valueToConvert is IConvertible) + { + convertedValue = Convert.ChangeType(valueToConvert, dataType); + } + + return convertedValue; + } + + protected override string ConvertValueToText(object value) + { + if (value == null) + value = string.Empty; + + MaskProvider.Set(value.ToString()); + return MaskProvider.ToDisplayString(); + } + + #endregion + + #region Event Handlers + + void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e) + { + //if the text is readonly do not add the text + if (TextBox.IsReadOnly) + { + e.Handled = true; + return; + } + + int position = TextBox.SelectionStart; + MaskedTextProvider provider = MaskProvider; + if (position < TextBox.Text.Length) + { + position = GetNextCharacterPosition(position); + + if (Keyboard.IsKeyToggled(Key.Insert)) + { + if (provider.Replace(e.Text, position)) + position++; + } + else + { + if (provider.InsertAt(e.Text, position)) + position++; + } + + position = GetNextCharacterPosition(position); + } + + UpdateText(provider, position); + e.Handled = true; + + base.OnPreviewTextInput(e); + } + + void TextBox_PreviewKeyDown(object sender, KeyEventArgs e) + { + base.OnPreviewKeyDown(e); + MaskedTextProvider provider = MaskProvider; + int position = TextBox.SelectionStart; + int selectionlength = TextBox.SelectionLength; + // If no selection use the start position else use end position + int endposition = (selectionlength == 0) ? position : position + selectionlength - 1; + + if (e.Key == Key.Delete && position < TextBox.Text.Length)//handle the delete key + { + if (provider.RemoveAt(position, endposition)) + UpdateText(provider, position); + + e.Handled = true; + } + else if (e.Key == Key.Space) + { + if (provider.InsertAt(" ", position)) + UpdateText(provider, position); + e.Handled = true; + } + else if (e.Key == Key.Back)//handle the back space + { + if ((position > 0) && (selectionlength == 0)) + { + position--; + if (provider.RemoveAt(position)) + UpdateText(provider, position); + } + + if (selectionlength != 0) + { + if (provider.RemoveAt(position, endposition)) + { + if (position > 0) + position--; + + UpdateText(provider, position); + } + } + + e.Handled = true; + } + } + + #endregion //Event Handlers + + #region Methods + + private void UpdateText(MaskedTextProvider provider, int position) + { + DisplayText = provider.ToDisplayString(); + + if (TextBox != null) + TextBox.SelectionStart = position; + } + + private int GetNextCharacterPosition(int startPosition) + { + int position = MaskProvider.FindEditPositionFrom(startPosition, true); + return position == -1 ? startPosition : position; + } + + private void ResolveMaskProvider(string mask) + { + MaskProvider = new MaskedTextProvider(mask) + { + IncludePrompt = this.IncludePrompt, + IncludeLiterals = this.IncludeLiterals + }; + } + + #endregion //Methods + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/NumericUpDown.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/NumericUpDown.cs index f9e3e28b..a927b71d 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/NumericUpDown.cs +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/NumericUpDown.cs @@ -1,10 +1,11 @@ using System; using System.Windows; using System.Globalization; +using Microsoft.Windows.Controls.Primitives; namespace Microsoft.Windows.Controls { - public class NumericUpDown : UpDownBase + public class NumericUpDown : UpDownBase { #region Properties @@ -23,10 +24,6 @@ namespace Microsoft.Windows.Controls nud.SetValidSpinDirection(); } - protected virtual void OnMinimumChanged(double oldValue, double newValue) - { - } - #endregion Minimum #region Maximum @@ -44,28 +41,17 @@ namespace Microsoft.Windows.Controls nud.SetValidSpinDirection(); } - protected virtual void OnMaximumChanged(double oldValue, double newValue) - { - } #endregion Maximum #region Increment - public static readonly DependencyProperty IncrementProperty = DependencyProperty.Register("Increment", typeof(double), typeof(NumericUpDown), new PropertyMetadata(1d, OnIncrementPropertyChanged)); + public static readonly DependencyProperty IncrementProperty = DependencyProperty.Register("Increment", typeof(double), typeof(NumericUpDown), new PropertyMetadata(1.0)); public double Increment { get { return (double)GetValue(IncrementProperty); } set { SetValue(IncrementProperty, value); } } - private static void OnIncrementPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - } - - protected virtual void OnIncrementChanged(double oldValue, double newValue) - { - } - #endregion #region FormatString @@ -85,7 +71,7 @@ namespace Microsoft.Windows.Controls protected virtual void OnStringFormatChanged(string oldValue, string newValue) { - Text = FormatValue(); + SyncTextAndValueProperties(InputBase.DisplayTextProperty, Value); } #endregion //FormatString @@ -97,7 +83,9 @@ namespace Microsoft.Windows.Controls static NumericUpDown() { DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericUpDown), new FrameworkPropertyMetadata(typeof(NumericUpDown))); - } + ValueTypeProperty.OverrideMetadata(typeof(NumericUpDown), new FrameworkPropertyMetadata(typeof(double))); + ValueProperty.OverrideMetadata(typeof(NumericUpDown), new FrameworkPropertyMetadata(default(Double))); + } #endregion //Constructors @@ -109,33 +97,55 @@ namespace Microsoft.Windows.Controls SetValidSpinDirection(); } - protected override void OnValueChanged(RoutedPropertyChangedEventArgs e) + protected override void OnValueChanged(object oldValue, object newValue) { SetValidSpinDirection(); } - protected override double ParseValue(string text) + protected override object ConvertTextToValue(string text) { NumberFormatInfo info = NumberFormatInfo.GetInstance(CultureInfo.CurrentCulture); if (text.Contains(info.PercentSymbol)) - return TryParcePercent(text, info); + { + if (ValueType == typeof(decimal)) + return TryParceDecimalPercent(text, info); + else + return TryParceDoublePercent(text, info); + } else - return TryParceDouble(text, info); + { + if (ValueType == typeof(decimal)) + return TryParceDecimal(text, info); + else if (ValueType == typeof(int)) + return TryParceInteger(text, info); + else + return TryParceDouble(text, info); + } } - protected internal override string FormatValue() + protected override string ConvertValueToText(object value) { - return Value.ToString(FormatString, CultureInfo.CurrentCulture); + return (Convert.ToDecimal(Value)).ToString(FormatString, CultureInfo.CurrentCulture); } protected override void OnIncrement() { - Value = (double)((decimal)Value + (decimal)Increment); + double newValue = (double)(Convert.ToDecimal(Value) + (decimal)Increment); + + if (ValueType != typeof(Double)) + Value = Convert.ChangeType(newValue, ValueType); + else + Value = newValue; } protected override void OnDecrement() { - Value = (double)((decimal)Value - (decimal)Increment); + double newValue = (double)(Convert.ToDecimal(Value) - (decimal)Increment); + + if (ValueType != typeof(Double)) + Value = Convert.ChangeType(newValue, ValueType); + else + Value = newValue; } #endregion //Base Class Overrides @@ -149,12 +159,12 @@ namespace Microsoft.Windows.Controls { ValidSpinDirections validDirections = ValidSpinDirections.None; - if (Value < Maximum) + if (Convert.ToDouble(Value) < Maximum) { validDirections = validDirections | ValidSpinDirections.Increase; } - if (Value > Minimum) + if (Convert.ToDouble(Value) > Minimum) { validDirections = validDirections | ValidSpinDirections.Decrease; } @@ -165,7 +175,7 @@ namespace Microsoft.Windows.Controls } } - private double TryParcePercent(string text, NumberFormatInfo info) + private double TryParceDoublePercent(string text, NumberFormatInfo info) { double result; text = text.Replace(info.PercentSymbol, null); @@ -173,14 +183,46 @@ namespace Microsoft.Windows.Controls return result / 100; } + private decimal TryParceDecimalPercent(string text, NumberFormatInfo info) + { + decimal result; + text = text.Replace(info.PercentSymbol, null); + result = TryParceDecimal(text, info); + return result / 100; + } + + private decimal TryParceDecimal(string text, NumberFormatInfo info) + { + decimal result; + if (!decimal.TryParse(text, NumberStyles.Any, info, out result)) + { + //an error occured now lets reset our value + result = Convert.ToDecimal(Value); + TextBox.Text = DisplayText = ConvertValueToText(result); + } + return result; + } + private double TryParceDouble(string text, NumberFormatInfo info) { double result; if (!double.TryParse(text, NumberStyles.Any, info, out result)) { - //an error occured now lets reset our value, text, and the text in the textbox - result = Value; - TextBox.Text = Text = FormatValue(); + //an error occured now lets reset our value + result = Convert.ToDouble(Value); + TextBox.Text = DisplayText = ConvertValueToText(result); + } + return result; + } + + private int TryParceInteger(string text, NumberFormatInfo info) + { + int result; + if (!int.TryParse(text, NumberStyles.Any, info, out result)) + { + //an error occured now lets reset our value + result = Convert.ToInt32(Value); + TextBox.Text = DisplayText = ConvertValueToText(result); } return result; } diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml index 5694227a..8e249531 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml @@ -494,11 +494,7 @@ - - + @@ -1091,7 +1087,7 @@ - + Text="{Binding DisplayText, RelativeSource={RelativeSource TemplatedParent}}" /> + + + + + + diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/UpDownBase/UpDownBase.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/UpDownBase/UpDownBase.cs deleted file mode 100644 index aed90390..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/UpDownBase/UpDownBase.cs +++ /dev/null @@ -1,321 +0,0 @@ -using System; -using System.Windows.Input; -using System.Windows.Controls; -using System.Windows; - -namespace Microsoft.Windows.Controls -{ - public abstract class UpDownBase : Control - { - #region Members - - /// - /// Name constant for Text template part. - /// - internal const string ElementTextName = "Text"; - - /// - /// 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 - /// - bool _isSyncingTextAndValueProperties; - - #endregion //Members - - #region Properties - - #region Value - - public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(T), typeof(UpDownBase), new FrameworkPropertyMetadata(default(T), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValuePropertyChanged)); - public virtual T Value - { - get { return (T)GetValue(ValueProperty); } - set { SetValue(ValueProperty, value); } - } - - private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - UpDownBase udb = (UpDownBase)d; - T oldValue = (T)e.OldValue; - T newValue = (T)e.NewValue; - - udb.SyncTextAndValueProperties(e.Property, e.NewValue); - - RoutedPropertyChangedEventArgs changedArgs = new RoutedPropertyChangedEventArgs(oldValue, newValue); - udb.OnValueChanged(changedArgs); - } - - protected virtual void OnValueChanged(RoutedPropertyChangedEventArgs e) - { - if (ValueChanged != null) - ValueChanged(this, e); - } - - #endregion //Value - - #region Text - - public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(UpDownBase), new FrameworkPropertyMetadata("0", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnTextPropertyChanged)); - public string Text - { - get { return (string)GetValue(TextProperty); } - set { SetValue(TextProperty, value); } - } - - private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - UpDownBase udb = (UpDownBase)d; - udb.SyncTextAndValueProperties(e.Property, e.NewValue); - } - - #endregion //Text - - #region IsEditable - - public static readonly DependencyProperty IsEditableProperty = DependencyProperty.Register("IsEditable", typeof(bool), typeof(UpDownBase), new PropertyMetadata(true, OnIsEditablePropertyChanged)); - public bool IsEditable - { - get { return (bool)GetValue(IsEditableProperty); } - set { SetValue(IsEditableProperty, value); } - } - - private static void OnIsEditablePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - UpDownBase source = d as UpDownBase; - source.OnIsEditableChanged((bool)e.OldValue, (bool)e.NewValue); - } - - protected virtual void OnIsEditableChanged(bool oldValue, bool newValue) - { - if (TextBox != null) - TextBox.IsReadOnly = !IsEditable; - } - - #endregion //IsEditable - - internal TextBox TextBox { get; private set; } - - private Spinner _spinner; - internal Spinner Spinner - { - get { return _spinner; } - private set - { - _spinner = value; - _spinner.Spin += OnSpinnerSpin; - } - } - - #endregion //Properties - - #region Constructors - - protected UpDownBase() { } - - #endregion //Constructors - - #region Base Class Overrides - - public override void OnApplyTemplate() - { - base.OnApplyTemplate(); - - TextBox = GetTemplateChild(ElementTextName) as TextBox; - Spinner = GetTemplateChild(ElementSpinnerName) as Spinner; - - if (TextBox != null) - TextBox.IsReadOnly = !IsEditable; - } - - protected override void OnPreviewKeyDown(KeyEventArgs e) - { - switch (e.Key) - { - case Key.Up: - { - DoIncrement(); - e.Handled = true; - break; - } - case Key.Down: - { - DoDecrement(); - e.Handled = true; - break; - } - case Key.Enter: - { - SyncTextAndValueProperties(UpDownBase.TextProperty, TextBox.Text); - break; - } - } - } - - protected override void OnMouseWheel(MouseWheelEventArgs e) - { - base.OnMouseWheel(e); - - if (!e.Handled) - { - if (e.Delta < 0) - { - DoDecrement(); - } - else if (0 < e.Delta) - { - DoIncrement(); - } - - e.Handled = true; - } - } - - #endregion //Base Class Overrides - - #region Methods - - #region Abstract - - /// - /// Called by ApplyValue to parse user input. - /// - /// User input. - /// Value parsed from user input. - protected abstract T ParseValue(string text); - - /// - /// Renders the value property into the textbox text. - /// - /// Formatted Value. - protected internal abstract string FormatValue(); - - /// - /// 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(); - - #endregion //Abstract - - #region Protected - - /// - /// GetValue override to return Value property as object type. - /// - /// The Value property as object type. - protected object GetValue() - { - return Value; - } - - /// - /// SetValue override to set value to Value property. - /// - /// New value. - protected void SetValue(object value) - { - Value = (T)value; - } - - #endregion //Protected - - #region Private - - /// - /// 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(); - } - } - - protected 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 (UpDownBase.TextProperty == p) - { - SetValue(UpDownBase.ValueProperty, ParseValue(newValue.ToString())); - } - - //we need to update the text no matter what because the user could have used the spin buttons to change dthe value - //or typed in the textbox so we need to reformat the entered value. - SetValue(UpDownBase.TextProperty, FormatValue()); - - _isSyncingTextAndValueProperties = false; - } - - #endregion //Private - - #region Virtual - - /// - /// Occurs when the spinner spins. - /// - /// Event args. - protected virtual void OnSpin(SpinEventArgs e) - { - if (e == null) - throw new ArgumentNullException("e"); - - if (e.Direction == SpinDirection.Increase) - DoIncrement(); - else - DoDecrement(); - } - - #endregion //Virtual - - #endregion //Methods - - #region Event Handlers - - /// - /// Event handler for Spinner template part's Spin event. - /// - /// The Spinner template part. - /// Event args. - private void OnSpinnerSpin(object sender, SpinEventArgs e) - { - OnSpin(e); - } - - #endregion //Event Handlers - - #region Events - - /// - /// Occurs when Value property has changed. - /// - public event RoutedPropertyChangedEventHandler ValueChanged; - - #endregion //Events - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj index ed35e03f..43da33d6 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj @@ -81,6 +81,8 @@ + + @@ -108,7 +110,7 @@ - + @@ -149,7 +151,7 @@ - +