我创建了下面的文本框,只接受可空的十进制数字。 当用户按下小数点分隔符时,光标跳至小数点。 我还创建了一个转换器,只是将空字符串修改为null。
它工作正常,但是在999.999.999,99之后,会触发一些奇怪的功能。当我尝试设置另一个数字时,光标跳到文本框中的随机位置,有时而不是按下的数字会在末尾添加零(0)。
这是我的代码, 文本框:
public class NumericTextBox : TextBox
{
char decimalSeperator;
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
decimalSeperator = Convert.ToChar(Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator);
DataObject.AddPastingHandler(this, PasteHandler);
this.KeyUp += NumericTextBox_KeyUp;
this.PreviewKeyDown += NumericTextBox_PreviewKeyDown;
this.PreviewTextInput += NumericTextBox_PreviewTextInput;
}
void NumericTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
if (!e.Text.IsDigitsOnly())
e.Handled = true;
}
void NumericTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
HandleWhiteSpace(e);
}
void NumericTextBox_KeyUp(object sender, KeyEventArgs e)
{
if (IsDecimalSeperator(e))
{
if (TextExists() && HasDecimalSeperator())
Select(Text.IndexOf(decimalSeperator) + 1, 0);
}
}
void PasteHandler(object sender, DataObjectPastingEventArgs e)
{
e.CancelCommand();
}
void HandleWhiteSpace(KeyEventArgs e)
{
if (e.Key == Key.Space)
e.Handled = true;
}
bool TextExists()
{
return !String.IsNullOrEmpty(Text) && Text.Length > 0;
}
bool IsDecimalSeperator(KeyEventArgs e)
{
return e.Key == Key.Decimal || e.Key == Key.OemComma;
}
bool HasDecimalSeperator()
{
return Text.IndexOf(decimalSeperator) > 0;
}
}
IsDigitsOnly扩展名:
public static class StringExtensions
{
public static bool IsDigitsOnly(this string str)
{
foreach (char c in str)
if (c < '0' || c > '9')
return false;
return true;
}
}
转换器:
public class EmptyStringToNullNumericConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value as string == string.Empty)
value = null;
return value;
}
}
和我的XAML:
<cc:NumericTextBox Grid.Row="8" Text="{Binding Cost, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, StringFormat='N2', Converter={StaticResource EmptyStringToNullNumericConverter}}"/>
“费用”属性是可为空的十进制。