创建功能性双重控制
Creating a functional Double Control
我有一个名为 DoubleNumericBox
的自定义控件,它验证并接受用户输入,例如 23,00
、0,9
、23.900,01
、34
... 等.
当我尝试将某些东西绑定到它时,问题就开始了。绑定不够可靠,有时控件不会显示新值,但如果我再设置一次 DataContext
它会设置值,等等
所以,我的自定义属性和事件一定是做错了什么。
自定义Properties/Events
- 值:
Double
- 最小值:
Double
- 最大值:
Double
值已更改:Event
预期行为
- 验证键入的键:数字、逗号和点(小数分隔符和数字分组字形)。我的文化使用
Comma
作为小数点分隔符。
验证整个文本 if (return 到最新的 Value
如果数字无效):
- 已粘贴文本。
- 失去焦点。
- 验证
Min/Max
限制。
- 接受来自
Text
或 Value
的绑定,并验证绑定值。
代码
public class DoubleNumericBox : TextBox
{
变量:
public readonly static DependencyProperty MinValueProperty;
public readonly static DependencyProperty ValueProperty;
public readonly static DependencyProperty MaxValueProperty;
属性:
public double MinValue
{
get { return (double)GetValue(MinValueProperty); }
set { SetCurrentValue(MinValueProperty, value); }
}
public double Value
{
get { return (double)GetValue(ValueProperty); }
set
{
SetCurrentValue(ValueProperty, value);
RaiseValueChangedEvent();
}
}
public double MaxValue
{
get { return (double)GetValue(MaxValueProperty); }
set { SetCurrentValue(MaxValueProperty, value); }
}
事件:
public static readonly RoutedEvent ValueChangedEvent;
public event RoutedEventHandler ValueChanged
{
//Provide CLR accessors for the event
add { AddHandler(ValueChangedEvent, value); }
remove { RemoveHandler(ValueChangedEvent, value); }
}
public void RaiseValueChangedEvent()
{
var newEventArgs = new RoutedEventArgs(ValueChangedEvent);
RaiseEvent(newEventArgs);
}
Constructor/Override:
static DoubleNumericBox()
{
MinValueProperty = DependencyProperty.Register("MinValue", typeof(double), typeof(DoubleNumericBox), new FrameworkPropertyMetadata(0D));
ValueProperty = DependencyProperty.Register("Value", typeof(double), typeof(DoubleNumericBox), new FrameworkPropertyMetadata(0D, ValueCallback));
MaxValueProperty = DependencyProperty.Register("MaxValue", typeof(double), typeof(DoubleNumericBox), new FrameworkPropertyMetadata(Double.MaxValue));
ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DoubleNumericBox));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
PreviewTextInput += DoubleNumericBox_PreviewTextInput;
ValueChanged += DoubleNumericBox_ValueChanged;
TextChanged += DoubleNumericBox_TextChanged;
LostFocus += DoubleNumericBox_LostFocus;
AddHandler(DataObject.PastingEvent, new DataObjectPastingEventHandler(PastingEvent));
}
事件:
private static void ValueCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var textBox = d as DoubleNumericBox;
if (textBox == null) return;
//textBox.Text = String.Format("{0:###,###,##0.0###}", textBox.Value);
textBox.RaiseValueChangedEvent();
}
private void DoubleNumericBox_ValueChanged(object sender, RoutedEventArgs e)
{
var textBox = sender as DoubleNumericBox;
if (textBox == null) return;
ValueChanged -= DoubleNumericBox_ValueChanged;
TextChanged -= DoubleNumericBox_TextChanged;
if (Value > MaxValue)
Value = MaxValue;
else if (Value < MinValue)
Value = MinValue;
textBox.Text = Text = String.Format("{0:###,###,##0.0###}", Value);
ValueChanged += DoubleNumericBox_ValueChanged;
TextChanged += DoubleNumericBox_TextChanged;
}
private void DoubleNumericBox_TextChanged(object sender, TextChangedEventArgs e)
{
var textBox = sender as TextBox;
if (textBox == null) return;
if (String.IsNullOrEmpty(textBox.Text)) return;
if (IsTextDisallowed(textBox.Text)) return;
ValueChanged -= DoubleNumericBox_ValueChanged;
var newValue = Convert.ToDouble(textBox.Text);
if (newValue > MaxValue)
Value = MaxValue;
else if (newValue < MinValue)
Value = MinValue;
else
{
Value = newValue;
}
ValueChanged += DoubleNumericBox_ValueChanged;
}
private void DoubleNumericBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
if (String.IsNullOrEmpty(e.Text))
{
e.Handled = true;
return;
}
//Only Numbers, comma and points.
if (IsEntryDisallowed(sender, e.Text))
{
e.Handled = true;
}
}
private void PastingEvent(object sender, DataObjectPastingEventArgs e)
{
if (e.DataObject.GetDataPresent(typeof(String)))
{
var text = (String)e.DataObject.GetData(typeof(String));
if (IsTextDisallowed(text))
{
e.CancelCommand();
}
}
else
{
e.CancelCommand();
}
}
private void DoubleNumericBox_LostFocus(object sender, RoutedEventArgs e)
{
TextChanged -= DoubleNumericBox_TextChanged;
Text = String.Format("{0:###,###,##0.0###}", Value);
TextChanged += DoubleNumericBox_TextChanged;
}
方法:
private bool IsEntryDisallowed(object sender, string text)
{
var regex = new Regex(@"^[0-9]|\.|\,$");
if (regex.IsMatch(text))
{
return !CheckPontuation(sender, text);
}
//Not a number or a Comma/Point.
return true;
}
private bool IsTextDisallowed(string text)
{
var regex = new Regex(@"^((\d+)|(\d{1,3}(\.\d{3})+)|(\d{1,3}(\.\d{3})(\,\d{3})+))((\,\d{4})|(\,\d{3})|(\,\d{2})|(\,\d{1})|(\,))?$");
return !regex.IsMatch(text); //\d+(?:,\d{1,2})?
}
private bool CheckPontuation(object sender, string next)
{
var textBox = sender as TextBox;
if (textBox == null) return true;
if (Char.IsNumber(next.ToCharArray()[0]))
return true;
if (next.Equals("."))
{
var textAux = textBox.Text;
if (!String.IsNullOrEmpty(textBox.SelectedText))
textAux = textAux.Replace(textBox.SelectedText, "");
//Check if the user can add a point mark here.
var before = textAux.Substring(0, textBox.SelectionStart);
var after = textAux.Substring(textBox.SelectionStart);
//If no text, return true.
if (String.IsNullOrEmpty(before) && String.IsNullOrEmpty(after)) return true;
if (!String.IsNullOrEmpty(before))
{
if (before.Contains(',')) return false;
if (after.Contains("."))
{
var split = before.Split('.');
if (split.Last().Length != 3) return false;
}
}
if (!String.IsNullOrEmpty(after))
{
var split = after.Split('.', ',');
if (split.First().Length != 3) return false;
}
return true;
}
//Only one comma.
if (next.Equals(","))
{
return !textBox.Text.Any(x => x.Equals(','));
}
return true;
}
}
你们能帮我改进这个自定义控件吗?
所以我在您的代码中看到了一些陷阱:
不要使用 += / -= 来连接 WPF 控件中的事件,它可以而且会破坏路由事件,请改用 Addhandler / RemoveHandler。
我删除了事件的取消挂钩和重新挂钩,并使用成员级别标志代替更改循环问题。这是我想出的代码,似乎可以很好地绑定到值字段。
旁注,您未能说明多个“.”在您的文本框中输入,以便用户可以键入 345.34.434.23,这不会被阻止。我知道要检查这个,因为我几年前写了一个 WPF FilterTextBox,这在我的测试中出现了。
public class DoubleNumericBox : TextBox
{
public readonly static DependencyProperty MinValueProperty;
public readonly static DependencyProperty ValueProperty;
public readonly static DependencyProperty MaxValueProperty;
public bool _bIgnoreChange = false;
public double MinValue
{
get { return (double)GetValue(MinValueProperty); }
set { SetCurrentValue(MinValueProperty, value); }
}
public double Value
{
get { return (double)GetValue(ValueProperty); }
set
{
SetCurrentValue(ValueProperty, value);
RaiseValueChangedEvent();
}
}
public double MaxValue
{
get { return (double)GetValue(MaxValueProperty); }
set { SetCurrentValue(MaxValueProperty, value); }
}
public static readonly RoutedEvent ValueChangedEvent;
public event RoutedEventHandler ValueChanged
{
//Provide CLR accessors for the event
add { AddHandler(ValueChangedEvent, value); }
remove { RemoveHandler(ValueChangedEvent, value); }
}
public void RaiseValueChangedEvent()
{
var newEventArgs = new RoutedEventArgs(ValueChangedEvent);
RaiseEvent(newEventArgs);
}
static DoubleNumericBox()
{
MinValueProperty = DependencyProperty.Register("MinValue", typeof(double), typeof(DoubleNumericBox), new FrameworkPropertyMetadata(0D));
ValueProperty = DependencyProperty.Register("Value", typeof(double), typeof(DoubleNumericBox), new FrameworkPropertyMetadata(0D, ValueCallback));
MaxValueProperty = DependencyProperty.Register("MaxValue", typeof(double), typeof(DoubleNumericBox), new FrameworkPropertyMetadata(Double.MaxValue));
ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DoubleNumericBox));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
AddHandler(TextBox.PreviewTextInputEvent, new TextCompositionEventHandler(DoubleNumericBox_PreviewTextInput));
AddHandler(TextBox.TextChangedEvent, new TextChangedEventHandler(DoubleNumericBox_TextChanged));
AddHandler(TextBox.LostFocusEvent, new RoutedEventHandler(DoubleNumericBox_LostFocus));
AddHandler(DataObject.PastingEvent, new DataObjectPastingEventHandler(PastingEvent));
}
private static void ValueCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var textBox = d as DoubleNumericBox;
if (textBox == null) return;
//textBox.Text = String.Format("{0:###,###,##0.0###}", textBox.Value);
textBox.DoubleNumericBox_ValueChanged();
}
private void DoubleNumericBox_ValueChanged()
{
if (Value > MaxValue)
Value = MaxValue;
else if (Value < MinValue)
Value = MinValue;
if (!_bIgnoreChange)
this.Text = Text = String.Format("{0:###,###,##0.0###}", Value);
}
private void DoubleNumericBox_TextChanged(object sender, TextChangedEventArgs e)
{
var textBox = sender as TextBox;
if (textBox == null) return;
if (String.IsNullOrEmpty(textBox.Text)) return;
if (IsTextDisallowed(textBox.Text)) return;
//ValueChanged -= DoubleNumericBox_ValueChanged;
_bIgnoreChange = true;
Value = Convert.ToDouble(textBox.Text);
//if (newValue > MaxValue)
// Value = MaxValue;
//else if (newValue < MinValue)
// Value = MinValue;
//else
//{
// Value = newValue;
//}
_bIgnoreChange = false;
//ValueChanged += DoubleNumericBox_ValueChanged;
}
private void DoubleNumericBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
if (String.IsNullOrEmpty(e.Text))
{
e.Handled = true;
return;
}
//Only Numbers, comma and points.
if (IsEntryDisallowed(sender, e.Text))
{
e.Handled = true;
}
}
private void PastingEvent(object sender, DataObjectPastingEventArgs e)
{
if (e.DataObject.GetDataPresent(typeof(String)))
{
var text = (String)e.DataObject.GetData(typeof(String));
if (IsTextDisallowed(text))
{
e.CancelCommand();
}
}
else
{
e.CancelCommand();
}
}
private void DoubleNumericBox_LostFocus(object sender, RoutedEventArgs e)
{
//TextChanged -= DoubleNumericBox_TextChanged;
Text = String.Format("{0:###,###,##0.0###}", Value);
//TextChanged += DoubleNumericBox_TextChanged;
}
private bool IsEntryDisallowed(object sender, string text)
{
var regex = new Regex(@"^[0-9]|\.|\,$");
if (regex.IsMatch(text))
{
return !CheckPontuation(sender, text);
}
//Not a number or a Comma/Point.
return true;
}
private bool IsTextDisallowed(string text)
{
var regex = new Regex(@"^((\d+)|(\d{1,3}(\.\d{3})+)|(\d{1,3}(\.\d{3})(\,\d{3})+))((\,\d{4})|(\,\d{3})|(\,\d{2})|(\,\d{1})|(\,))?$");
return !regex.IsMatch(text); //\d+(?:,\d{1,2})?
}
private bool CheckPontuation(object sender, string next)
{
var textBox = sender as TextBox;
if (textBox == null) return true;
if (Char.IsNumber(next.ToCharArray()[0]))
return true;
if (next.Equals("."))
{
var textAux = textBox.Text;
if (!String.IsNullOrEmpty(textBox.SelectedText))
textAux = textAux.Replace(textBox.SelectedText, "");
//Check if the user can add a point mark here.
var before = textAux.Substring(0, textBox.SelectionStart);
var after = textAux.Substring(textBox.SelectionStart);
//If no text, return true.
if (String.IsNullOrEmpty(before) && String.IsNullOrEmpty(after)) return true;
if (!String.IsNullOrEmpty(before))
{
if (before.Contains(',')) return false;
if (after.Contains("."))
{
var split = before.Split('.');
if (split.Last().Length != 3) return false;
}
}
if (!String.IsNullOrEmpty(after))
{
var split = after.Split('.', ',');
if (split.First().Length != 3) return false;
}
return true;
}
//Only one comma.
if (next.Equals(","))
{
return !textBox.Text.Any(x => x.Equals(','));
}
return true;
}
}
我有一个名为 DoubleNumericBox
的自定义控件,它验证并接受用户输入,例如 23,00
、0,9
、23.900,01
、34
... 等.
当我尝试将某些东西绑定到它时,问题就开始了。绑定不够可靠,有时控件不会显示新值,但如果我再设置一次 DataContext
它会设置值,等等
所以,我的自定义属性和事件一定是做错了什么。
自定义Properties/Events
- 值:
Double
- 最小值:
Double
- 最大值:
Double
值已更改:Event
预期行为
- 验证键入的键:数字、逗号和点(小数分隔符和数字分组字形)。我的文化使用
Comma
作为小数点分隔符。 验证整个文本 if (return 到最新的
Value
如果数字无效):- 已粘贴文本。
- 失去焦点。
- 验证
Min/Max
限制。 - 接受来自
Text
或Value
的绑定,并验证绑定值。
代码
public class DoubleNumericBox : TextBox
{
变量:
public readonly static DependencyProperty MinValueProperty;
public readonly static DependencyProperty ValueProperty;
public readonly static DependencyProperty MaxValueProperty;
属性:
public double MinValue
{
get { return (double)GetValue(MinValueProperty); }
set { SetCurrentValue(MinValueProperty, value); }
}
public double Value
{
get { return (double)GetValue(ValueProperty); }
set
{
SetCurrentValue(ValueProperty, value);
RaiseValueChangedEvent();
}
}
public double MaxValue
{
get { return (double)GetValue(MaxValueProperty); }
set { SetCurrentValue(MaxValueProperty, value); }
}
事件:
public static readonly RoutedEvent ValueChangedEvent;
public event RoutedEventHandler ValueChanged
{
//Provide CLR accessors for the event
add { AddHandler(ValueChangedEvent, value); }
remove { RemoveHandler(ValueChangedEvent, value); }
}
public void RaiseValueChangedEvent()
{
var newEventArgs = new RoutedEventArgs(ValueChangedEvent);
RaiseEvent(newEventArgs);
}
Constructor/Override:
static DoubleNumericBox()
{
MinValueProperty = DependencyProperty.Register("MinValue", typeof(double), typeof(DoubleNumericBox), new FrameworkPropertyMetadata(0D));
ValueProperty = DependencyProperty.Register("Value", typeof(double), typeof(DoubleNumericBox), new FrameworkPropertyMetadata(0D, ValueCallback));
MaxValueProperty = DependencyProperty.Register("MaxValue", typeof(double), typeof(DoubleNumericBox), new FrameworkPropertyMetadata(Double.MaxValue));
ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DoubleNumericBox));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
PreviewTextInput += DoubleNumericBox_PreviewTextInput;
ValueChanged += DoubleNumericBox_ValueChanged;
TextChanged += DoubleNumericBox_TextChanged;
LostFocus += DoubleNumericBox_LostFocus;
AddHandler(DataObject.PastingEvent, new DataObjectPastingEventHandler(PastingEvent));
}
事件:
private static void ValueCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var textBox = d as DoubleNumericBox;
if (textBox == null) return;
//textBox.Text = String.Format("{0:###,###,##0.0###}", textBox.Value);
textBox.RaiseValueChangedEvent();
}
private void DoubleNumericBox_ValueChanged(object sender, RoutedEventArgs e)
{
var textBox = sender as DoubleNumericBox;
if (textBox == null) return;
ValueChanged -= DoubleNumericBox_ValueChanged;
TextChanged -= DoubleNumericBox_TextChanged;
if (Value > MaxValue)
Value = MaxValue;
else if (Value < MinValue)
Value = MinValue;
textBox.Text = Text = String.Format("{0:###,###,##0.0###}", Value);
ValueChanged += DoubleNumericBox_ValueChanged;
TextChanged += DoubleNumericBox_TextChanged;
}
private void DoubleNumericBox_TextChanged(object sender, TextChangedEventArgs e)
{
var textBox = sender as TextBox;
if (textBox == null) return;
if (String.IsNullOrEmpty(textBox.Text)) return;
if (IsTextDisallowed(textBox.Text)) return;
ValueChanged -= DoubleNumericBox_ValueChanged;
var newValue = Convert.ToDouble(textBox.Text);
if (newValue > MaxValue)
Value = MaxValue;
else if (newValue < MinValue)
Value = MinValue;
else
{
Value = newValue;
}
ValueChanged += DoubleNumericBox_ValueChanged;
}
private void DoubleNumericBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
if (String.IsNullOrEmpty(e.Text))
{
e.Handled = true;
return;
}
//Only Numbers, comma and points.
if (IsEntryDisallowed(sender, e.Text))
{
e.Handled = true;
}
}
private void PastingEvent(object sender, DataObjectPastingEventArgs e)
{
if (e.DataObject.GetDataPresent(typeof(String)))
{
var text = (String)e.DataObject.GetData(typeof(String));
if (IsTextDisallowed(text))
{
e.CancelCommand();
}
}
else
{
e.CancelCommand();
}
}
private void DoubleNumericBox_LostFocus(object sender, RoutedEventArgs e)
{
TextChanged -= DoubleNumericBox_TextChanged;
Text = String.Format("{0:###,###,##0.0###}", Value);
TextChanged += DoubleNumericBox_TextChanged;
}
方法:
private bool IsEntryDisallowed(object sender, string text)
{
var regex = new Regex(@"^[0-9]|\.|\,$");
if (regex.IsMatch(text))
{
return !CheckPontuation(sender, text);
}
//Not a number or a Comma/Point.
return true;
}
private bool IsTextDisallowed(string text)
{
var regex = new Regex(@"^((\d+)|(\d{1,3}(\.\d{3})+)|(\d{1,3}(\.\d{3})(\,\d{3})+))((\,\d{4})|(\,\d{3})|(\,\d{2})|(\,\d{1})|(\,))?$");
return !regex.IsMatch(text); //\d+(?:,\d{1,2})?
}
private bool CheckPontuation(object sender, string next)
{
var textBox = sender as TextBox;
if (textBox == null) return true;
if (Char.IsNumber(next.ToCharArray()[0]))
return true;
if (next.Equals("."))
{
var textAux = textBox.Text;
if (!String.IsNullOrEmpty(textBox.SelectedText))
textAux = textAux.Replace(textBox.SelectedText, "");
//Check if the user can add a point mark here.
var before = textAux.Substring(0, textBox.SelectionStart);
var after = textAux.Substring(textBox.SelectionStart);
//If no text, return true.
if (String.IsNullOrEmpty(before) && String.IsNullOrEmpty(after)) return true;
if (!String.IsNullOrEmpty(before))
{
if (before.Contains(',')) return false;
if (after.Contains("."))
{
var split = before.Split('.');
if (split.Last().Length != 3) return false;
}
}
if (!String.IsNullOrEmpty(after))
{
var split = after.Split('.', ',');
if (split.First().Length != 3) return false;
}
return true;
}
//Only one comma.
if (next.Equals(","))
{
return !textBox.Text.Any(x => x.Equals(','));
}
return true;
}
}
你们能帮我改进这个自定义控件吗?
所以我在您的代码中看到了一些陷阱: 不要使用 += / -= 来连接 WPF 控件中的事件,它可以而且会破坏路由事件,请改用 Addhandler / RemoveHandler。 我删除了事件的取消挂钩和重新挂钩,并使用成员级别标志代替更改循环问题。这是我想出的代码,似乎可以很好地绑定到值字段。
旁注,您未能说明多个“.”在您的文本框中输入,以便用户可以键入 345.34.434.23,这不会被阻止。我知道要检查这个,因为我几年前写了一个 WPF FilterTextBox,这在我的测试中出现了。
public class DoubleNumericBox : TextBox
{
public readonly static DependencyProperty MinValueProperty;
public readonly static DependencyProperty ValueProperty;
public readonly static DependencyProperty MaxValueProperty;
public bool _bIgnoreChange = false;
public double MinValue
{
get { return (double)GetValue(MinValueProperty); }
set { SetCurrentValue(MinValueProperty, value); }
}
public double Value
{
get { return (double)GetValue(ValueProperty); }
set
{
SetCurrentValue(ValueProperty, value);
RaiseValueChangedEvent();
}
}
public double MaxValue
{
get { return (double)GetValue(MaxValueProperty); }
set { SetCurrentValue(MaxValueProperty, value); }
}
public static readonly RoutedEvent ValueChangedEvent;
public event RoutedEventHandler ValueChanged
{
//Provide CLR accessors for the event
add { AddHandler(ValueChangedEvent, value); }
remove { RemoveHandler(ValueChangedEvent, value); }
}
public void RaiseValueChangedEvent()
{
var newEventArgs = new RoutedEventArgs(ValueChangedEvent);
RaiseEvent(newEventArgs);
}
static DoubleNumericBox()
{
MinValueProperty = DependencyProperty.Register("MinValue", typeof(double), typeof(DoubleNumericBox), new FrameworkPropertyMetadata(0D));
ValueProperty = DependencyProperty.Register("Value", typeof(double), typeof(DoubleNumericBox), new FrameworkPropertyMetadata(0D, ValueCallback));
MaxValueProperty = DependencyProperty.Register("MaxValue", typeof(double), typeof(DoubleNumericBox), new FrameworkPropertyMetadata(Double.MaxValue));
ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DoubleNumericBox));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
AddHandler(TextBox.PreviewTextInputEvent, new TextCompositionEventHandler(DoubleNumericBox_PreviewTextInput));
AddHandler(TextBox.TextChangedEvent, new TextChangedEventHandler(DoubleNumericBox_TextChanged));
AddHandler(TextBox.LostFocusEvent, new RoutedEventHandler(DoubleNumericBox_LostFocus));
AddHandler(DataObject.PastingEvent, new DataObjectPastingEventHandler(PastingEvent));
}
private static void ValueCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var textBox = d as DoubleNumericBox;
if (textBox == null) return;
//textBox.Text = String.Format("{0:###,###,##0.0###}", textBox.Value);
textBox.DoubleNumericBox_ValueChanged();
}
private void DoubleNumericBox_ValueChanged()
{
if (Value > MaxValue)
Value = MaxValue;
else if (Value < MinValue)
Value = MinValue;
if (!_bIgnoreChange)
this.Text = Text = String.Format("{0:###,###,##0.0###}", Value);
}
private void DoubleNumericBox_TextChanged(object sender, TextChangedEventArgs e)
{
var textBox = sender as TextBox;
if (textBox == null) return;
if (String.IsNullOrEmpty(textBox.Text)) return;
if (IsTextDisallowed(textBox.Text)) return;
//ValueChanged -= DoubleNumericBox_ValueChanged;
_bIgnoreChange = true;
Value = Convert.ToDouble(textBox.Text);
//if (newValue > MaxValue)
// Value = MaxValue;
//else if (newValue < MinValue)
// Value = MinValue;
//else
//{
// Value = newValue;
//}
_bIgnoreChange = false;
//ValueChanged += DoubleNumericBox_ValueChanged;
}
private void DoubleNumericBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
if (String.IsNullOrEmpty(e.Text))
{
e.Handled = true;
return;
}
//Only Numbers, comma and points.
if (IsEntryDisallowed(sender, e.Text))
{
e.Handled = true;
}
}
private void PastingEvent(object sender, DataObjectPastingEventArgs e)
{
if (e.DataObject.GetDataPresent(typeof(String)))
{
var text = (String)e.DataObject.GetData(typeof(String));
if (IsTextDisallowed(text))
{
e.CancelCommand();
}
}
else
{
e.CancelCommand();
}
}
private void DoubleNumericBox_LostFocus(object sender, RoutedEventArgs e)
{
//TextChanged -= DoubleNumericBox_TextChanged;
Text = String.Format("{0:###,###,##0.0###}", Value);
//TextChanged += DoubleNumericBox_TextChanged;
}
private bool IsEntryDisallowed(object sender, string text)
{
var regex = new Regex(@"^[0-9]|\.|\,$");
if (regex.IsMatch(text))
{
return !CheckPontuation(sender, text);
}
//Not a number or a Comma/Point.
return true;
}
private bool IsTextDisallowed(string text)
{
var regex = new Regex(@"^((\d+)|(\d{1,3}(\.\d{3})+)|(\d{1,3}(\.\d{3})(\,\d{3})+))((\,\d{4})|(\,\d{3})|(\,\d{2})|(\,\d{1})|(\,))?$");
return !regex.IsMatch(text); //\d+(?:,\d{1,2})?
}
private bool CheckPontuation(object sender, string next)
{
var textBox = sender as TextBox;
if (textBox == null) return true;
if (Char.IsNumber(next.ToCharArray()[0]))
return true;
if (next.Equals("."))
{
var textAux = textBox.Text;
if (!String.IsNullOrEmpty(textBox.SelectedText))
textAux = textAux.Replace(textBox.SelectedText, "");
//Check if the user can add a point mark here.
var before = textAux.Substring(0, textBox.SelectionStart);
var after = textAux.Substring(textBox.SelectionStart);
//If no text, return true.
if (String.IsNullOrEmpty(before) && String.IsNullOrEmpty(after)) return true;
if (!String.IsNullOrEmpty(before))
{
if (before.Contains(',')) return false;
if (after.Contains("."))
{
var split = before.Split('.');
if (split.Last().Length != 3) return false;
}
}
if (!String.IsNullOrEmpty(after))
{
var split = after.Split('.', ',');
if (split.First().Length != 3) return false;
}
return true;
}
//Only one comma.
if (next.Equals(","))
{
return !textBox.Text.Any(x => x.Equals(','));
}
return true;
}
}