wpf文本框自定义控件类型错误
我在TextBox上编写了自定义控件,该控件还具有以下最小和最大输入:wpf文本框自定义控件类型错误,wpf,custom-controls,Wpf,Custom Controls,我在TextBox上编写了自定义控件,该控件还具有以下最小和最大输入: public class NumericTextBox : TextBox { static NumericTextBox() { DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericTextBox), new FrameworkPropertyMetadata(typeof(NumericTex
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;
}
}
公共类NumericTextBox:TextBox
{
静态NumericTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericTextBox),new FrameworkPropertyMetadata(typeof(NumericTextBox));
}
公共静态只读从属属性MinimumProperty=
DependencyProperty.Register(“最小”、typeof(int)、typeof(NumericTextBox)、new PropertyMetadata(默认值(int));
公共整数最小值
{
获取{return(int)GetValue(MinimumProperty);}
set{SetValue(MinimumProperty,value);}
}
公共静态只读从属属性MaximumProperty=
DependencyProperty.Register(“最大”、typeof(int)、typeof(NumericTextBox)、新PropertyMetadata(100));
公共整数最大值
{
获取{return(int)GetValue(MaximumProperty);}
set{SetValue(MaximumProperty,value);}
}
公共新静态只读DependencyProperty TextProperty=
DependencyProperty.Register(“文本”、typeof(int)、typeof(NumericTextBox),
新框架属性元数据(
默认值(int),
默认情况下,FrameworkPropertyMetadataOptions.BindsTwoWay,
无效的
强制电流值),
有效);
公共新整型文本
{
获取{return(int)GetValue(TextProperty);}
set{SetValue(TextProperty,value);}
}
私有静态对象强制当前值(DependencyObject d,object baseValue)
{
var numericTextBox=(numericTextBox)d;
var intValue=(int)baseValue;
如果(intValuenumericTextBox.max)intValue=numericTextBox.max;
如果((int)baseValue!=intValue)
numericTextBox.Text=intValue;
返回值;
}
私有静态bool有效(对象值)
{
如果(值==null)
返回false;
int值;
var result=Int32.TryParse(value.ToString(),out intValue);
返回结果;
}
}
在我的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:Path=Text;
DataItem='NumericTextBox'(名称='';目标元素是“TextBox”
(名称=“”);目标属性为“Text”(类型为“String”)
FormatException:'System.FormatException:输入字符串不在
格式正确。在System.Number.StringTonNumber(字符串str,
NumberStyles选项、NumberBuffer&number、NumberFormatInfo信息、,
System.Number.ParseInt32(字符串s,
NumberStyles样式,NumberFormatInfo)位于
System.String.System.IConvertible.ToInt32(IFormatProvider)在System.Convert.ChangeType(对象值、类型转换类型、, IFormatProvider)位于 MS.Internal.Data.SystemConvertConverter.ConvertBack(对象o,类型 类型、对象参数、CultureInfo区域性)位于 System.Windows.Data.BindingExpression.ConvertBackHelper(IValueConverter 转换器、对象值、类型sourceType、对象参数、, 文化信息(文化)' 这可能是因为TextBox中的原始文本属性是字符串。。。但我不确定。
请帮忙。你做得不对。您没有将
文本框的输入限制为仅输入数字。框架正在尝试将字符串
转换为int
,以适合新的int文本
属性,但正如错误所述:输入字符串的格式不正确,例如,不是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
控件。当然,您还需要将最小值
和最大值
属性实现为AttachedProperties
,但是您可以这样做:
<TextBox Text={Binding Test} Attached:TextBoxProperties.IsNumeric="True"
Attached:TextBoxProperties.Minimum="0" Attached:TextBoxProperties.Maximum="100" />
您的解决方案不依赖于依赖项属性绑定特性,而是依赖于PreviewKeyDown事件。我更喜欢使用DP验证和强制功能。这样,我可以在文本框周围有一个红色边框来表示不正确的值。例如,你更愿意让用户输入不正确的值并提醒他们这一事实,而不是简单地不允许他们输入不正确的值?有趣。要做到这一点,我宁愿使用或界面来提供完整的用户反馈。然而,选择当然是你的。这是一个UI设计的问题。。。例如,用户应该如何知道只允许数字。IDataErrorInfo也是一个显示通用消息的选项,如“只允许数字”-但同样,它应该在自定义控件上实现,而不是在视图模型上实现。你的解决方案很好,但是。。。我可能会坚持下去。但是
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));
}