wpf文本框自定义控件类型错误

时间:2013-10-06 14:24:33

标签: wpf custom-controls

我在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属性是字符串...但我不确定。 请协助。

1 个答案:

答案 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控件。当然,您需要将MinimumMaximum属性实现为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));
}