我在TextBox上编写了自定义控件,它还具有最小和最大输入,如下所示:
public class NumericTextBox : TextBox
{
static NumericTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericTextBox), new FrameworkPropertyMetadata(typeof(NumericTextBox)));
}
public static readonly DependencyProperty MinimumProperty =
DependencyProperty.Register("Minimum", typeof(int), typeof(NumericTextBox), new PropertyMetadata(default(int)));
public int Minimum
{
get { return (int)GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
}
public static readonly DependencyProperty MaximumProperty =
DependencyProperty.Register("Maximum", typeof(int), typeof(NumericTextBox), new PropertyMetadata(100));
public int Maximum
{
get { return (int)GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
}
public new static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(int), typeof(NumericTextBox),
new FrameworkPropertyMetadata(
default(int),
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
null,
CoerceCurrentValue),
IsValid);
public new int Text
{
get { return (int)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
private static object CoerceCurrentValue(DependencyObject d, object baseValue)
{
var numericTextBox = (NumericTextBox)d;
var intValue = (int)baseValue;
if (intValue < numericTextBox.Minimum) intValue = numericTextBox.Minimum;
if (intValue > numericTextBox.Maximum) intValue = numericTextBox.Maximum;
if ((int)baseValue != intValue)
numericTextBox.Text = intValue;
return intValue;
}
private static bool IsValid(object value)
{
if (value == null)
return false;
int intValue;
var result = Int32.TryParse(value.ToString(), out intValue);
return result;
}
}
在我的xaml中我称之为:
<controls:NumericTextBox
Grid.Row="0"
Grid.Column="1"
Margin="5"
VerticalAlignment="Center"
Text="{Binding Test, UpdateSourceTrigger=PropertyChanged}"
Minimum="0"
Maximum="100"
/>
它绑定到我的视图模型中的Test属性(作为int)。 一切都很好,直到我输入一个字符,我得到绑定错误:
System.Windows.Data错误:7:ConvertBack无法转换值'1a' (输入'String')。 BindingExpression:路径=文本; DataItem ='NumericTextBox'(Name ='');目标元素是'TextBox' (名称= ''); target属性是'Text'(类型'String') FormatException:'System.FormatException:输入字符串不在 格式正确。在System.Number.StringToNumber(String str, NumberStyles选项,NumberBuffer&amp; number,NumberFormatInfo信息, System.Number.ParseInt32(String s,Boolean s,Boolean parseDecimal) NumberStyles样式,NumberFormatInfo信息)at System.String.System.IConvertible.ToInt32(IFormatProvider provider)
在System.Convert.ChangeType(对象值,类型conversionType, IFormatProvider提供商) MS.Internal.Data.SystemConvertConverter.ConvertBack(Object o,Type type,Object parameter,CultureInfo culture)at System.Windows.Data.BindingExpression.ConvertBackHelper(的IValueConverter converter,Object value,Type sourceType,Object parameter, CultureInfo culture)'
可能是因为TextBox中的原始Text属性是字符串...但我不确定。 请协助。
答案 0 :(得分:1)
你是以错误的方式解决这个问题。您不是将TextBox
的输入限制为仅限数字。框架正在尝试将string
转换为int
以适合您的new int Text
属性,但正如错误所示:输入字符串的格式不正确。,例如。不是int
。尝试将其添加到构造函数中:
PreviewTextInput += new TextCompositionEventHandler((s, e) => e.Handled =
!e.Text.All(c => Char.IsNumber(c) && c != ' '));
PreviewKeyDown += new KeyEventHandler((s, e) => e.Handled = e.Key == Key.Space);
如果输入了非数字值,他们只需将e.Handled
设置为true
即可,这会在这些情况下忽略输入。
此外,您不需要实现自己的Text
属性......这只是令人困惑的问题。只需使用原始值并将值解析为int
,只要您需要,请确保将为数字。我认为这两个处理程序应该确保这一点。如果您有任何问题,请告诉我。
另一个想法是使用这些处理程序创建AttachedProperty
,然后您可以将其应用于任何TextBox
控件。当然,您需要将Minimum
和Maximum
属性实现为AttachedProperties
,但之后您可以执行以下操作:
<TextBox Text={Binding Test} Attached:TextBoxProperties.IsNumeric="True"
Attached:TextBoxProperties.Minimum="0" Attached:TextBoxProperties.Maximum="100" />
您可以在MSDN上的Attached Properties Overview页面上找到更多信息。
更新&gt;&gt;&gt;
如果您不希望用户能够删除TextBox
中的最后一个字符,那么我们可以更改其中一个处理程序以禁止它:
PreviewKeyDown += PreviewKeyDown;
...
private void PreviewKeyDown(object sender, KeyEventArgs e)
{
TextBox textBox = sender as TextBox;
e.Handled = e.Key == Key.Space ||
(textBox.Text.Length == 1 && (e.Key == Key.Delete || e.Key == Key.Back));
}