Browse Source

Major overhaul of NumericUpDown, DateTimeUpDown, and MaskedTextBox in order to support null values. Need extensive testing because I am sure I broke something.

pull/1645/head
brianlagunas_cp 15 years ago
parent
commit
faa7825423
  1. 146
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/InputBase.cs
  2. 12
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/UpDownBase.cs
  3. 134
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/DateTimeUpDown/Implementation/DateTimeUpDown.cs
  4. 189
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MaskedTextBox/Implementation/MaskedTextBox.cs
  5. 285
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/NumericUpDown.cs
  6. 4
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyGrid.cs
  7. 1
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj

146
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/InputBase.cs

@ -6,20 +6,8 @@ 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 IsEditable
public static readonly DependencyProperty IsEditableProperty = DependencyProperty.Register("IsEditable", typeof(bool), typeof(InputBase), new PropertyMetadata(true));
@ -33,19 +21,17 @@ namespace Microsoft.Windows.Controls.Primitives
#region Text
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(InputBase), new FrameworkPropertyMetadata(default(String), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnTextPropertyChanged));
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(InputBase), new PropertyMetadata(default(String), OnTextPropertyChanged));
public string Text
{
get { return (string)this.GetValue(TextProperty); }
set { this.SetValue(TextProperty, value); }
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
InputBase input = (InputBase)d;
input.OnTextChanged((string)e.OldValue, (string)e.NewValue);
if (input._isInitialized)
input.SyncTextAndValueProperties(e.Property, e.NewValue);
}
protected virtual void OnTextChanged(string previousValue, string currentValue)
@ -55,132 +41,6 @@ namespace Microsoft.Windows.Controls.Primitives
#endregion //Text
#region Value
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(InputBase), new FrameworkPropertyMetadata(default(object), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValuePropertyChanged, OnCoerceValuePropertyCallback));
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)
{
RoutedPropertyChangedEventArgs<object> args = new RoutedPropertyChangedEventArgs<object>(oldValue, newValue);
args.RoutedEvent = InputBase.ValueChangedEvent;
RaiseEvent(args);
}
private static object OnCoerceValuePropertyCallback(DependencyObject d, object baseValue)
{
InputBase inputBase = d as InputBase;
if (inputBase != null)
return inputBase.OnCoerceValue(baseValue);
else
return baseValue;
}
protected virtual object OnCoerceValue(object value)
{
return value;
}
#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(TextProperty, Text);
}
#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 Events
public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<object>), typeof(InputBase));
public event RoutedPropertyChangedEventHandler<object> ValueChanged
{
add { AddHandler(ValueChangedEvent, value); }
remove { RemoveHandler(ValueChangedEvent, value); }
}
#endregion //Events
#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.TextProperty == p)
{
SetValue(InputBase.ValueProperty, ConvertTextToValue(newValue.ToString()));
}
SetValue(InputBase.TextProperty, ConvertValueToText(newValue));
_isSyncingTextAndValueProperties = false;
}
#endregion //Methods
#region Abstract
protected abstract object ConvertTextToValue(string text);
protected abstract string ConvertValueToText(object value);
#endregion //Abstract
}
}

12
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/UpDownBase.cs

@ -95,12 +95,12 @@ namespace Microsoft.Windows.Controls.Primitives
e.Handled = true;
break;
}
case Key.Enter:
{
if (IsEditable)
SyncTextAndValueProperties(UpDownBase.TextProperty, TextBox.Text);
break;
}
//case Key.Enter:
// {
// if (IsEditable)
// SyncTextAndValueProperties(UpDownBase.TextProperty, TextBox.Text);
// break;
// }
}
}

134
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/DateTimeUpDown/Implementation/DateTimeUpDown.cs

@ -14,6 +14,7 @@ namespace Microsoft.Windows.Controls
private List<DateTimeInfo> _dateTimeInfoList = new List<DateTimeInfo>();
private DateTimeInfo _selectedDateTimeInfo;
private bool _fireSelectionChangedEvent = true;
private bool _isSyncingTextAndValueProperties;
#endregion //Members
@ -21,6 +22,8 @@ namespace Microsoft.Windows.Controls
private DateTimeFormatInfo DateTimeFormatInfo { get; set; }
//TODO: add minimum and maximum properties
#region Format
public static readonly DependencyProperty FormatProperty = DependencyProperty.Register("Format", typeof(DateTimeFormat), typeof(DateTimeUpDown), new UIPropertyMetadata(DateTimeFormat.FullDateTime, OnFormatChanged));
@ -72,6 +75,58 @@ namespace Microsoft.Windows.Controls
#endregion //FormatString
#region Value
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(DateTime?), typeof(DateTimeUpDown), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValueChanged, OnCoerceValue));
public DateTime? Value
{
get { return (DateTime?)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
private static object OnCoerceValue(DependencyObject o, object value)
{
DateTimeUpDown dateTimeUpDown = o as DateTimeUpDown;
if (dateTimeUpDown != null)
return dateTimeUpDown.OnCoerceValue((DateTime?)value);
else
return value;
}
protected virtual DateTime? OnCoerceValue(DateTime? value)
{
//if the user entered a string value to represent a date or time, we need to parse that string into a valid DatTime value
if (value != null && !(value is DateTime))
{
return DateTime.Parse(value.ToString(), DateTimeFormatInfo);
}
return value;
}
private static void OnValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
DateTimeUpDown dateTimeUpDown = o as DateTimeUpDown;
if (dateTimeUpDown != null)
dateTimeUpDown.OnValueChanged((DateTime?)e.OldValue, (DateTime?)e.NewValue);
}
protected virtual void OnValueChanged(DateTime? oldValue, DateTime? newValue)
{
//whenever the value changes we need to parse out the value into out DateTimeInfo segments so we can keep track of the individual pieces
//but only if it is not null
if (newValue != null)
ParseValueIntoDateTimeInfo();
SyncTextAndValueProperties(DateTimeUpDown.ValueProperty, newValue);
RoutedPropertyChangedEventArgs<DateTime?> args = new RoutedPropertyChangedEventArgs<DateTime?>(oldValue, newValue);
args.RoutedEvent = DateTimeUpDown.ValueChangedEvent;
RaiseEvent(args);
}
#endregion //Value
#endregion //Properties
#region Constructors
@ -79,7 +134,6 @@ namespace Microsoft.Windows.Controls
static DateTimeUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DateTimeUpDown), new FrameworkPropertyMetadata(typeof(DateTimeUpDown)));
ValueTypeProperty.OverrideMetadata(typeof(DateTimeUpDown), new FrameworkPropertyMetadata(typeof(Nullable<DateTime>)));
}
public DateTimeUpDown()
@ -130,27 +184,6 @@ namespace Microsoft.Windows.Controls
base.OnPreviewKeyDown(e);
}
protected override void OnValueChanged(object oldValue, object newValue)
{
//whenever the value changes we need to parse out the value into out DateTimeInfo segments so we can keep track of the individual pieces
//but only if it is not null
if (newValue != null)
ParseValueIntoDateTimeInfo();
base.OnValueChanged(oldValue, newValue);
}
protected override object OnCoerceValue(object value)
{
//if the user entered a string value to represent a date or time, we need to parse that string into a valid DatTime value
if (value != null && !(value is DateTime))
{
return DateTime.Parse(value.ToString(), DateTimeFormatInfo);
}
return base.OnCoerceValue(value);
}
#endregion //Base Class Overrides
#region Event Hanlders
@ -165,6 +198,17 @@ namespace Microsoft.Windows.Controls
#endregion //Event Hanlders
#region Events
public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<DateTime?>), typeof(DateTimeUpDown));
public event RoutedPropertyChangedEventHandler<DateTime?> ValueChanged
{
add { AddHandler(ValueChangedEvent, value); }
remove { RemoveHandler(ValueChangedEvent, value); }
}
#endregion //Events
#region Methods
#region Abstract
@ -181,19 +225,6 @@ namespace Microsoft.Windows.Controls
UpdateDateTime(-1);
}
protected override object ConvertTextToValue(string text)
{
throw new NotImplementedException("ConvertTextToValue");
}
protected override string ConvertValueToText(object value)
{
if (value == null) return string.Empty;
DateTime dt = DateTime.Parse(value.ToString(), CultureInfo.CurrentCulture);
return dt.ToString(GetFormatString(Format), CultureInfo.CurrentCulture);
}
#endregion //Abstract
#region Private
@ -539,6 +570,39 @@ namespace Microsoft.Windows.Controls
#endregion //Private
protected object ConvertTextToValue(string text)
{
throw new NotImplementedException("ConvertTextToValue");
}
protected string ConvertValueToText(object value)
{
if (value == null) return string.Empty;
DateTime dt = DateTime.Parse(value.ToString(), CultureInfo.CurrentCulture);
return dt.ToString(GetFormatString(Format), CultureInfo.CurrentCulture);
}
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.TextProperty == p)
{
string text = newValue == null ? String.Empty : newValue.ToString();
SetValue(DateTimeUpDown.ValueProperty, ConvertTextToValue(text));
}
SetValue(InputBase.TextProperty, ConvertValueToText(newValue));
_isSyncingTextAndValueProperties = false;
}
#endregion //Methods
}
}

189
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MaskedTextBox/Implementation/MaskedTextBox.cs

@ -9,6 +9,16 @@ namespace Microsoft.Windows.Controls
{
public class MaskedTextBox : InputBase
{
#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
protected MaskedTextProvider MaskProvider { get; set; }
@ -84,6 +94,58 @@ namespace Microsoft.Windows.Controls
#endregion //Mask
#region Value
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(MaskedTextBox), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValueChanged));
public object Value
{
get { return (object)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
private static void OnValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
MaskedTextBox maskedTextBox = o as MaskedTextBox;
if (maskedTextBox != null)
maskedTextBox.OnValueChanged((object)e.OldValue, (object)e.NewValue);
}
protected virtual void OnValueChanged(object oldValue, object newValue)
{
if (_isInitialized)
SyncTextAndValueProperties(DateTimeUpDown.ValueProperty, newValue);
RoutedPropertyChangedEventArgs<object> args = new RoutedPropertyChangedEventArgs<object>(oldValue, newValue);
args.RoutedEvent = MaskedTextBox.ValueChangedEvent;
RaiseEvent(args);
}
#endregion //Value
#region ValueType
public static readonly DependencyProperty ValueTypeProperty = DependencyProperty.Register("ValueType", typeof(Type), typeof(MaskedTextBox), new UIPropertyMetadata(typeof(String), OnValueTypeChanged));
public Type ValueType
{
get { return (Type)GetValue(ValueTypeProperty); }
set { SetValue(ValueTypeProperty, value); }
}
private static void OnValueTypeChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
MaskedTextBox maskedTextBox = o as MaskedTextBox;
if (maskedTextBox != null)
maskedTextBox.OnValueTypeChanged((Type)e.OldValue, (Type)e.NewValue);
}
protected virtual void OnValueTypeChanged(Type oldValue, Type newValue)
{
if (_isInitialized)
SyncTextAndValueProperties(InputBase.TextProperty, Text);
}
#endregion //ValueType
#endregion //Properties
#region Constructors
@ -115,48 +177,27 @@ namespace Microsoft.Windows.Controls
base.OnAccessKey(e);
}
protected override object ConvertTextToValue(string text)
protected override void OnGotFocus(RoutedEventArgs e)
{
object convertedValue = null;
Type dataType = ValueType;
if (TextBox != null)
TextBox.Focus();
}
string valueToConvert = MaskProvider.ToString();
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
if (valueToConvert.GetType() == dataType || dataType.IsInstanceOfType(valueToConvert))
{
convertedValue = valueToConvert;
}
#if !VS2008
else if (String.IsNullOrWhiteSpace(valueToConvert))
{
convertedValue = Activator.CreateInstance(dataType);
}
#else
else if (String.IsNullOrEmpty(valueToConvert))
if (!_isInitialized)
{
convertedValue = Activator.CreateInstance(dataType);
_isInitialized = true;
SyncTextAndValueProperties(ValueProperty, Value);
}
#endif
else if (null == convertedValue && valueToConvert is IConvertible)
{
convertedValue = Convert.ChangeType(valueToConvert, dataType);
}
return convertedValue;
}
protected override string ConvertValueToText(object value)
protected override void OnTextChanged(string previousValue, string currentValue)
{
if (value == null)
value = string.Empty;
//I have only seen this occur while in Blend, but we need it here so the Blend designer doesn't crash.
if (MaskProvider == null)
return value.ToString();
MaskProvider.Set(value.ToString());
return MaskProvider.ToDisplayString();
if (_isInitialized)
SyncTextAndValueProperties(InputBase.TextProperty, currentValue);
}
#endregion
@ -247,6 +288,17 @@ namespace Microsoft.Windows.Controls
#endregion //Event Handlers
#region Events
public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<object>), typeof(MaskedTextBox));
public event RoutedPropertyChangedEventHandler<object> ValueChanged
{
add { AddHandler(ValueChangedEvent, value); }
remove { RemoveHandler(ValueChangedEvent, value); }
}
#endregion //Events
#region Methods
#region Private
@ -284,20 +336,69 @@ namespace Microsoft.Windows.Controls
#endregion //Private
#region Public
private object ConvertTextToValue(string text)
{
object convertedValue = null;
/// <summary>
/// Attempts to set focus to this element.
/// </summary>
public new void Focus()
Type dataType = ValueType;
string valueToConvert = MaskProvider.ToString().Trim();
if (valueToConvert.GetType() == dataType || dataType.IsInstanceOfType(valueToConvert))
{
convertedValue = valueToConvert;
}
#if !VS2008
else if (String.IsNullOrWhiteSpace(valueToConvert))
{
convertedValue = Activator.CreateInstance(dataType);
}
#else
else if (String.IsNullOrEmpty(valueToConvert))
{
convertedValue = Activator.CreateInstance(dataType);
}
#endif
else if (null == convertedValue && valueToConvert is IConvertible)
{
convertedValue = Convert.ChangeType(valueToConvert, dataType);
}
return convertedValue;
}
private string ConvertValueToText(object value)
{
if (TextBox != null)
TextBox.Focus();
else
base.Focus();
if (value == null)
value = string.Empty;
//I have only seen this occur while in Blend, but we need it here so the Blend designer doesn't crash.
if (MaskProvider == null)
return value.ToString();
MaskProvider.Set(value.ToString());
return MaskProvider.ToDisplayString();
}
#endregion //Public
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.TextProperty == p)
{
if (newValue != null)
SetValue(MaskedTextBox.ValueProperty, ConvertTextToValue(newValue.ToString()));
}
SetValue(InputBase.TextProperty, ConvertValueToText(newValue));
_isSyncingTextAndValueProperties = false;
}
#endregion //Methods

285
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/NumericUpDown.cs

@ -8,6 +8,15 @@ namespace Microsoft.Windows.Controls
{
public class NumericUpDown : UpDownBase
{
#region Members
/// <summary>
/// Flags if the Text and Value properties are in the process of being sync'd
/// </summary>
private bool _isSyncingTextAndValueProperties;
#endregion //Members
#region Properties
#region Minimum
@ -88,6 +97,64 @@ namespace Microsoft.Windows.Controls
#endregion //SelectAllOnGotFocus
#region Value
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(decimal?), typeof(NumericUpDown), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValueChanged, OnCoerceValue));
public decimal? Value
{
get { return (decimal?)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
private static object OnCoerceValue(DependencyObject o, object value)
{
NumericUpDown numericUpDown = o as NumericUpDown;
if (numericUpDown != null)
return numericUpDown.OnCoerceValue((decimal?)value);
else
return value;
}
protected virtual decimal? OnCoerceValue(decimal? value)
{
if (value == null) return value;
decimal val = value.Value;
if (val < Minimum)
{
return Minimum;
}
else if (val > Maximum)
{
return Maximum;
}
else
{
return value;
}
}
private static void OnValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
NumericUpDown numericUpDown = o as NumericUpDown;
if (numericUpDown != null)
numericUpDown.OnValueChanged((decimal?)e.OldValue, (decimal?)e.NewValue);
}
protected virtual void OnValueChanged(decimal? oldValue, decimal? newValue)
{
SetValidSpinDirection();
SyncTextAndValueProperties(NumericUpDown.ValueProperty, newValue);
RoutedPropertyChangedEventArgs<decimal?> args = new RoutedPropertyChangedEventArgs<decimal?>(oldValue, newValue);
args.RoutedEvent = NumericUpDown.ValueChangedEvent;
RaiseEvent(args);
}
#endregion //Value
#endregion
#region Constructors
@ -95,14 +162,20 @@ namespace Microsoft.Windows.Controls
static NumericUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericUpDown), new FrameworkPropertyMetadata(typeof(NumericUpDown)));
ValueTypeProperty.OverrideMetadata(typeof(NumericUpDown), new FrameworkPropertyMetadata(typeof(decimal)));
ValueProperty.OverrideMetadata(typeof(NumericUpDown), new FrameworkPropertyMetadata(default(decimal)));
}
#endregion //Constructors
#region Base Class Overrides
protected override void OnAccessKey(AccessKeyEventArgs e)
{
if (TextBox != null)
TextBox.Focus();
base.OnAccessKey(e);
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
@ -116,93 +189,38 @@ namespace Microsoft.Windows.Controls
}
}
protected override void OnAccessKey(AccessKeyEventArgs e)
{
if (TextBox != null)
TextBox.Focus();
base.OnAccessKey(e);
}
protected override void OnGotFocus(RoutedEventArgs e)
{
if (TextBox != null)
TextBox.Focus();
}
protected override void OnValueChanged(object oldValue, object newValue)
protected override void OnIncrement()
{
SetValidSpinDirection();
base.OnValueChanged(oldValue, newValue);
if (Value.HasValue)
Value += Increment;
}
protected override object OnCoerceValue(object value)
protected override void OnDecrement()
{
if (value == null) return value;
decimal val = Convert.ToDecimal(value);
if (val < Minimum)
{
return Minimum;
}
else if (val > Maximum)
{
return Maximum;
}
else
{
return value;
}
if (Value.HasValue)
Value -= Increment;
}
protected override object ConvertTextToValue(string text)
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
object result = null;
NumberFormatInfo info = NumberFormatInfo.GetInstance(CultureInfo.CurrentCulture);
try
{
result = FormatString.Contains("P") ? ParsePercent(text, ValueType, info) : ParseDataValue(text, ValueType, info);
}
catch
{
TextBox.Text = Text = ConvertValueToText(Value);
return Value;
}
base.OnPreviewKeyDown(e);
return result;
}
protected override string ConvertValueToText(object value)
{
//TODO: create GetTextFromValue methods for each data type;
if (value is double)
if (e.Key == Key.Enter)
{
double d = (double)value;
if (Double.IsNaN(d))
return "NaN";
else if (Double.IsPositiveInfinity(d) || Double.MaxValue == d)
return "Infinity";
else if (Double.IsNegativeInfinity(d) || Double.MinValue == d)
return "Negative-Infinity";
if (IsEditable)
SyncTextAndValueProperties(InputBase.TextProperty, TextBox.Text);
}
return (Convert.ToDecimal(Value)).ToString(FormatString, CultureInfo.CurrentCulture);
}
protected override void OnIncrement()
{
decimal newValue = (Convert.ToDecimal(Value) + Increment);
Value = ValueType != typeof(Decimal) ? Convert.ChangeType(newValue, ValueType) : newValue;
}
protected override void OnDecrement()
protected override void OnTextChanged(string previousValue, string currentValue)
{
decimal newValue = (Convert.ToDecimal(Value) - Increment);
Value = ValueType != typeof(Decimal) ? Convert.ChangeType(newValue, ValueType) : newValue;
SyncTextAndValueProperties(InputBase.TextProperty, currentValue);
}
#endregion //Base Class Overrides
@ -225,75 +243,67 @@ namespace Microsoft.Windows.Controls
#endregion //Event Handlers
#region Methods
#region Events
/// <summary>
/// Sets the valid spin direction based on current value, minimum and maximum.
/// </summary>
private void SetValidSpinDirection()
public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<decimal?>), typeof(NumericUpDown));
public event RoutedPropertyChangedEventHandler<decimal?> ValueChanged
{
ValidSpinDirections validDirections = ValidSpinDirections.None;
add { AddHandler(ValueChangedEvent, value); }
remove { RemoveHandler(ValueChangedEvent, value); }
}
if (Convert.ToDecimal(Value) < Maximum)
{
validDirections = validDirections | ValidSpinDirections.Increase;
}
#endregion //Events
if (Convert.ToDecimal(Value) > Minimum)
{
validDirections = validDirections | ValidSpinDirections.Decrease;
}
#region Methods
if (Spinner != null)
{
Spinner.ValidSpinDirection = validDirections;
}
}
private decimal? ConvertTextToValue(string text)
{
decimal? result = null;
#region Parsing
if (String.IsNullOrEmpty(text))
return result;
NumberFormatInfo info = NumberFormatInfo.GetInstance(CultureInfo.CurrentCulture);
private static object ParseDataValue(string text, Type dataType, NumberFormatInfo info)
{
try
{
if (typeof(decimal) == dataType)
{
return ParseDecimal(text, info);
}
else if (typeof(double) == dataType)
{
return ParseDouble(text, info);
}
else if (typeof(float) == dataType)
{
return ParseFloat(text, info);
}
else if (typeof(byte) == dataType || typeof(sbyte) == dataType ||
typeof(short) == dataType || typeof(ushort) == dataType || typeof(Int16) == dataType ||
typeof(int) == dataType || typeof(uint) == dataType || typeof(Int32) == dataType ||
typeof(long) == dataType || typeof(ulong) == dataType || typeof(Int64) == dataType)
{
return ParseWholeNumber(text, dataType, info);
}
else
{
throw new ArgumentException("Type not supported");
}
result = FormatString.Contains("P") ? ParsePercent(text, info) : ParseDecimal(text, info);
}
catch (Exception ex)
catch
{
throw;
Text = ConvertValueToText(Value);
return Value;
}
return result;
}
private static double ParseDouble(string text, NumberFormatInfo info)
private string ConvertValueToText(object value)
{
return double.Parse(text, NumberStyles.Any, info);
if (!Value.HasValue)
return String.Empty;
return Value.Value.ToString(FormatString, CultureInfo.CurrentCulture);
}
private static float ParseFloat(string text, NumberFormatInfo info)
private void SyncTextAndValueProperties(DependencyProperty p, object newValue)
{
return float.Parse(text, NumberStyles.Any, info);
//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(NumericUpDown.ValueProperty, ConvertTextToValue(text));
}
SetValue(InputBase.TextProperty, ConvertValueToText(newValue));
_isSyncingTextAndValueProperties = false;
}
private static decimal ParseDecimal(string text, NumberFormatInfo info)
@ -301,23 +311,38 @@ namespace Microsoft.Windows.Controls
return decimal.Parse(text, NumberStyles.Any, info);
}
private static object ParseWholeNumber(string text, Type dataType, NumberFormatInfo info)
{
decimal result = decimal.Parse(text, NumberStyles.Any, info);
return Convert.ChangeType(result, dataType, info);
}
private static object ParsePercent(string text, Type dataType, NumberFormatInfo info)
private static decimal ParsePercent(string text, NumberFormatInfo info)
{
text = text.Replace(info.PercentSymbol, null);
decimal result = decimal.Parse(text, NumberStyles.Any, info);
result = result / 100;
return Convert.ChangeType(result, dataType, info);
return result;
}
#endregion
/// <summary>
/// Sets the valid spin direction based on current value, minimum and maximum.
/// </summary>
private void SetValidSpinDirection()
{
ValidSpinDirections validDirections = ValidSpinDirections.None;
if (Convert.ToDecimal(Value) < Maximum)
{
validDirections = validDirections | ValidSpinDirections.Increase;
}
if (Convert.ToDecimal(Value) > Minimum)
{
validDirections = validDirections | ValidSpinDirections.Decrease;
}
if (Spinner != null)
{
Spinner.ValidSpinDirection = validDirections;
}
}
#endregion //Methods
}

4
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyGrid.cs

@ -322,9 +322,7 @@ namespace Microsoft.Windows.Controls.PropertyGrid
editor = new TextBlockEditor();
else if (propertyItem.PropertyType == typeof(bool))
editor = new CheckBoxEditor();
else if (propertyItem.PropertyType == typeof(int))
editor = new IntegerUpDownEditor();
else if (propertyItem.PropertyType == typeof(double))
else if (propertyItem.PropertyType == typeof(double) || propertyItem.PropertyType == typeof(int))
editor = new NumericUpDownEditor();
else if (propertyItem.PropertyType == typeof(DateTime))
editor = new DateTimeUpDownEditor();

1
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj

@ -210,7 +210,6 @@
<Compile Include="PropertyGrid\Implementation\Editors\EnumComboBoxEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\FontComboBoxEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\ICustomTypeEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\IntegerUpDownEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\ITypeEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\NumericUpDownEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\TextBlockEditor.cs" />

Loading…
Cancel
Save