Browse Source

Made a lot of changes, and possible breaking changes:

1. added new MaskedTextBox control
2. no longer have UpDownBase<T>
3. NumericUpDown now has new base class.  Hopefully I didn't break anything, but I know I did :0)
4. By default the NumericUpDown uses doubles.  To use anything else such as decimals or int you must specify the ValueType accordingly.
<extToolkit:NumericUpDown Grid.Row="1" Value="{Binding Age}" Increment="1" Minimum="18" Maximum="65" ValueType="{x:Type sys:Int32}" />
pull/1645/head
brianlagunas_cp 15 years ago
parent
commit
34e7fd56df
  1. 107
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ChildWindow/ChildWindow.cs
  2. 159
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/InputBase.cs
  3. 162
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/UpDownBase.cs
  4. 255
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MaskedTextBox/MaskedTextBox.cs
  5. 108
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/NumericUpDown.cs
  6. 32
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml
  7. 321
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/UpDownBase/UpDownBase.cs
  8. 6
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj

107
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;
}
}

159
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
/// <summary>
/// Flags if the Text and Value properties are in the process of being sync'd
/// </summary>
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
}
}

162
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
/// <summary>
/// Name constant for Text template part.
/// </summary>
internal const string ElementTextName = "TextBox";
/// <summary>
/// Name constant for Spinner template part.
/// </summary>
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();
}
/// <summary>
/// Performs an increment if conditions allow it.
/// </summary>
private void DoDecrement()
{
if (Spinner == null || (Spinner.ValidSpinDirection & ValidSpinDirections.Decrease) == ValidSpinDirections.Decrease)
{
OnDecrement();
}
}
/// <summary>
/// Performs a decrement if conditions allow it.
/// </summary>
private void DoIncrement()
{
if (Spinner == null || (Spinner.ValidSpinDirection & ValidSpinDirections.Increase) == ValidSpinDirections.Increase)
{
OnIncrement();
}
}
#region Abstract
/// <summary>
/// Called by OnSpin when the spin direction is SpinDirection.Increase.
/// </summary>
protected abstract void OnIncrement();
/// <summary>
/// Called by OnSpin when the spin direction is SpinDirection.Descrease.
/// </summary>
protected abstract void OnDecrement();
#endregion //Abstract
#endregion //Methods
}
}

255
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
}
}

108
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<double>
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<double> 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;
}

32
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml

@ -494,11 +494,7 @@
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="PART_Overlay" HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="0" RenderTransformOrigin="0.5,0.5"
Background="{TemplateBinding OverlayBrush}"
Opacity="{TemplateBinding OverlayOpacity}"
Visibility="{TemplateBinding IsModal, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<Grid x:Name="PART_WindowRoot" HorizontalAlignment="Left" VerticalAlignment="Top">
<Grid x:Name="PART_WindowRoot" HorizontalAlignment="Left" VerticalAlignment="Top" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform />
@ -1091,7 +1087,7 @@
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:NumericUpDown}">
<local:ButtonSpinner x:Name="Spinner" IsTabStop="False">
<TextBox x:Name="Text" BorderThickness="0"
<TextBox x:Name="TextBox" BorderThickness="0"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontStretch="{TemplateBinding FontStretch}"
@ -1100,13 +1096,35 @@
Foreground="{TemplateBinding Foreground}"
MinWidth="20" AcceptsReturn="False"
TextAlignment="Right" TextWrapping="NoWrap"
Text="{Binding Text, RelativeSource={RelativeSource TemplatedParent}}" />
Text="{Binding DisplayText, RelativeSource={RelativeSource TemplatedParent}}" />
</local:ButtonSpinner>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- =============================================================================== -->
<!-- MaskedTextBox -->
<!-- =============================================================================== -->
<Style TargetType="{x:Type local:MaskedTextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MaskedTextBox}">
<TextBox x:Name="TextBox"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontStretch="{TemplateBinding FontStretch}"
FontStyle="{TemplateBinding FontStyle}"
FontWeight="{TemplateBinding FontWeight}"
Foreground="{TemplateBinding Foreground}"
MinWidth="20" AcceptsReturn="False" TextWrapping="NoWrap"
Text="{Binding DisplayText, RelativeSource={RelativeSource TemplatedParent}}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- =============================================================================== -->
<!-- Magnifier -->
<!-- =============================================================================== -->

321
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/UpDownBase/UpDownBase.cs

@ -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<T> : Control
{
#region Members
/// <summary>
/// Name constant for Text template part.
/// </summary>
internal const string ElementTextName = "Text";
/// <summary>
/// Name constant for Spinner template part.
/// </summary>
internal const string ElementSpinnerName = "Spinner";
/// <summary>
/// Flags if the Text and Value properties are in the process of being sync'd
/// </summary>
bool _isSyncingTextAndValueProperties;
#endregion //Members
#region Properties
#region Value
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(T), typeof(UpDownBase<T>), 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<T> udb = (UpDownBase<T>)d;
T oldValue = (T)e.OldValue;
T newValue = (T)e.NewValue;
udb.SyncTextAndValueProperties(e.Property, e.NewValue);
RoutedPropertyChangedEventArgs<T> changedArgs = new RoutedPropertyChangedEventArgs<T>(oldValue, newValue);
udb.OnValueChanged(changedArgs);
}
protected virtual void OnValueChanged(RoutedPropertyChangedEventArgs<T> e)
{
if (ValueChanged != null)
ValueChanged(this, e);
}
#endregion //Value
#region Text
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(UpDownBase<T>), 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<T> udb = (UpDownBase<T>)d;
udb.SyncTextAndValueProperties(e.Property, e.NewValue);
}
#endregion //Text
#region IsEditable
public static readonly DependencyProperty IsEditableProperty = DependencyProperty.Register("IsEditable", typeof(bool), typeof(UpDownBase<T>), 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<T> source = d as UpDownBase<T>;
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<T>.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
/// <summary>
/// Called by ApplyValue to parse user input.
/// </summary>
/// <param name="text">User input.</param>
/// <returns>Value parsed from user input.</returns>
protected abstract T ParseValue(string text);
/// <summary>
/// Renders the value property into the textbox text.
/// </summary>
/// <returns>Formatted Value.</returns>
protected internal abstract string FormatValue();
/// <summary>
/// Called by OnSpin when the spin direction is SpinDirection.Increase.
/// </summary>
protected abstract void OnIncrement();
/// <summary>
/// Called by OnSpin when the spin direction is SpinDirection.Descrease.
/// </summary>
protected abstract void OnDecrement();
#endregion //Abstract
#region Protected
/// <summary>
/// GetValue override to return Value property as object type.
/// </summary>
/// <returns>The Value property as object type.</returns>
protected object GetValue()
{
return Value;
}
/// <summary>
/// SetValue override to set value to Value property.
/// </summary>
/// <param name="value">New value.</param>
protected void SetValue(object value)
{
Value = (T)value;
}
#endregion //Protected
#region Private
/// <summary>
/// Performs an increment if conditions allow it.
/// </summary>
private void DoDecrement()
{
if (Spinner == null || (Spinner.ValidSpinDirection & ValidSpinDirections.Decrease) == ValidSpinDirections.Decrease)
{
OnDecrement();
}
}
/// <summary>
/// Performs a decrement if conditions allow it.
/// </summary>
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<T>.TextProperty == p)
{
SetValue(UpDownBase<T>.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<T>.TextProperty, FormatValue());
_isSyncingTextAndValueProperties = false;
}
#endregion //Private
#region Virtual
/// <summary>
/// Occurs when the spinner spins.
/// </summary>
/// <param name="e">Event args.</param>
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
/// <summary>
/// Event handler for Spinner template part's Spin event.
/// </summary>
/// <param name="sender">The Spinner template part.</param>
/// <param name="e">Event args.</param>
private void OnSpinnerSpin(object sender, SpinEventArgs e)
{
OnSpin(e);
}
#endregion //Event Handlers
#region Events
/// <summary>
/// Occurs when Value property has changed.
/// </summary>
public event RoutedPropertyChangedEventHandler<T> ValueChanged;
#endregion //Events
}
}

6
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj

@ -81,6 +81,8 @@
<Compile Include="Magnifier\Magnifier.cs" />
<Compile Include="Magnifier\MagnifierAdorner.cs" />
<Compile Include="Magnifier\MagnifierManager.cs" />
<Compile Include="Core\Primitives\InputBase.cs" />
<Compile Include="MaskedTextBox\MaskedTextBox.cs" />
<Compile Include="MessageBox\MessageBox.cs" />
<Compile Include="NumericUpDown\NumericUpDown.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
@ -108,7 +110,7 @@
<Compile Include="RichTextBox\Formatters\RtfFormatter.cs" />
<Compile Include="RichTextBox\Formatters\XamlFormatter.cs" />
<Compile Include="RichTextBox\RichTextBox.cs" />
<Compile Include="UpDownBase\UpDownBase.cs" />
<Compile Include="Core\Primitives\UpDownBase.cs" />
<Compile Include="VisualStates.cs" />
<Compile Include="MessageBox\VisualStates.MessageBox.cs" />
<EmbeddedResource Include="Properties\Resources.resx">
@ -149,7 +151,7 @@
<Resource Include="RichTextBoxFormatBar\Images\Underline16.png" />
</ItemGroup>
<ItemGroup>
<Folder Include="Core\Primitives\" />
<Folder Include="UpDownBase\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

Loading…
Cancel
Save