此类为TextBox的一个扩展类,其中包含四个附加属性,分别是:
属性 | IntegerRange | Minimum | Maximum | PreviousValue |
---|---|---|---|---|
类型 | bool | int | int | string |
定义 | 是否启用范围判定 | 最小值 | 最大值 | 前一个有效值 |
默认值 | false | 0 | int的最大值 | 空 |
实现了以下功能:
- 若输入的值不满足最小值和最大值的范围或输入不合法时,则会自动恢复为前一个有效值
- 解决了粘贴时的输入验证问题
- 解决了用户选中文本后输入的问题
- 解决了当最小值大于9时,无法输入数字的问题
源代码:
public static class TextBoxExtensions
{
#region IntegerRange
public static readonly DependencyProperty IntegerRangeProperty =
DependencyProperty.RegisterAttached(
"IntegerRange",
typeof(bool),
typeof(TextBoxExtensions),
new PropertyMetadata(false, OnIntegerRangeChanged));
public static bool GetIntegerRange(DependencyObject target)
{
return (bool)target.GetValue(IntegerRangeProperty);
}
public static void SetIntegerRange(DependencyObject target, bool value)
{
target.SetValue(IntegerRangeProperty, value);
}
#endregion
#region Minimum
public static readonly DependencyProperty MinimumProperty =
DependencyProperty.RegisterAttached(
"Minimum",
typeof(int),
typeof(TextBoxExtensions),
new PropertyMetadata(0));
public static int GetMinimum(DependencyObject target)
{
return (int)target.GetValue(MinimumProperty);
}
public static void SetMinimum(DependencyObject target, int value)
{
target.SetValue(MinimumProperty, value);
}
#endregion
#region Maximum
public static readonly DependencyProperty MaximumProperty =
DependencyProperty.RegisterAttached(
"Maximum",
typeof(int),
typeof(TextBoxExtensions),
new PropertyMetadata(int.MaxValue));
public static int GetMaximum(DependencyObject target)
{
return (int)target.GetValue(MaximumProperty);
}
public static void SetMaximum(DependencyObject target, int value)
{
target.SetValue(MaximumProperty, value);
}
#endregion
#region PreviousValue
public static readonly DependencyProperty PreviousValueProperty =
DependencyProperty.RegisterAttached("PreviousValue", typeof(string), typeof(TextBoxExtensions));
public static string GetPreviousValue(DependencyObject obj)
{
return (string)obj.GetValue(PreviousValueProperty);
}
public static void SetPreviousValue(DependencyObject obj, string value)
{
obj.SetValue(PreviousValueProperty, value);
}
#endregion
private static void OnIntegerRangeChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
TextBox textBox = sender as TextBox;
if (textBox != null)
{
if ((bool)e.NewValue)
{
textBox.PreviewTextInput += TextBox_PreviewTextInput;
DataObject.AddPastingHandler(textBox, TextBox_Pasting);
textBox.LostFocus += TextBox_LostFocus;
}
else
{
textBox.PreviewTextInput -= TextBox_PreviewTextInput;
DataObject.RemovePastingHandler(textBox, TextBox_Pasting);
textBox.LostFocus -= TextBox_LostFocus;
}
}
}
private static void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
TextBox textBox = (TextBox)sender;
string fullText = textBox.SelectionLength > 0
? textBox.Text.Remove(textBox.SelectionStart, textBox.SelectionLength).Insert(textBox.SelectionStart, e.Text)
: textBox.Text.Insert(textBox.SelectionStart, e.Text);
int value;
int maximum = GetMaximum(textBox);
if (!int.TryParse(fullText, out value) || value > maximum)
{
e.Handled = true;
}
else
{
// If the text is valid, update the PreviousValue property
SetPreviousValue(textBox, textBox.Text);
}
}
private static void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
TextBox textBox = (TextBox)sender;
double minimum = GetMinimum(textBox);
double maximum = GetMaximum(textBox);
if (double.TryParse(textBox.Text, out var value) && (value < minimum || value > maximum ))
{
textBox.Text = GetPreviousValue(textBox);
}
}
private static void TextBox_Pasting(object sender, DataObjectPastingEventArgs e)
{
TextBox textBox = (TextBox)sender;
string pasteText = e.DataObject.GetData(typeof(string)) as string;
string fullText = textBox.SelectionLength > 0
? textBox.Text.Remove(textBox.SelectionStart, textBox.SelectionLength).Insert(textBox.SelectionStart, pasteText)
: textBox.Text.Insert(textBox.SelectionStart, pasteText);
int value;
int minimum = GetMinimum(textBox);
int maximum = GetMaximum(textBox);
if (!int.TryParse(fullText, out value) || value < minimum || value > maximum)
{
e.CancelCommand();
}
}
}