我正在尝试创建自己非常简单的继承自TextBox的NumberBox,它验证丢失焦点的输入并根据指定的小数位格式化值。一切都很好,直到有人提出一些无效的价值。
如果值无效,我想将NumberBox留空而不是0.0。将其重置为有效值(如0.0)将跳过我在代码中所需的字段验证检查。
我试过this.Text =“”但是会触发绑定异常“输入字符串格式不正确”
如果我尝试this.ClearValue(TextProperty),它会清除文本框但也会删除绑定。知道如何实现这个或更好的NumberBox而不是工具包吗?
public delegate void ValueChangedHandler(object sender, EventArgs args);
public class NumberBox : TextBox
{
public event ValueChangedHandler ValueChanged;
public NumberBox()
{
this.DefaultStyleKey = typeof(TextBox);
this.LostFocus += new RoutedEventHandler(NumberBox_LostFocus);
}
public static readonly DependencyProperty DecimalPlacesProperty = DependencyProperty.Register(
"DecimalPlaces",
typeof(int),
typeof(NumberBox),
new PropertyMetadata(2));
public static readonly DependencyProperty MaxValueProperty = DependencyProperty.Register(
"MaxValue",
typeof(double),
typeof(NumberBox),
new PropertyMetadata(Double.MaxValue));
public static readonly DependencyProperty MinValueProperty = DependencyProperty.Register(
"MinValue",
typeof(double),
typeof(NumberBox),
new PropertyMetadata(0.0));
public int DecimalPlaces
{
get
{
return (int)this.GetValue(DecimalPlacesProperty);
}
set
{
base.SetValue(DecimalPlacesProperty, value);
}
}
public Double MaxValue
{
get
{
return (Double)this.GetValue(MaxValueProperty);
}
set
{
base.SetValue(MaxValueProperty, value);
}
}
public Double MinValue
{
get
{
return (Double)this.GetValue(MinValueProperty);
}
set
{
base.SetValue(MinValueProperty, value);
}
}
void NumberBox_LostFocus(object sender, RoutedEventArgs e)
{
double result;
//if (this.Text.Trim().Length == 0)
// return;
if (double.TryParse(this.Text, out result))
{
result = Math.Min(result, this.MaxValue);
result = Math.Max(result, this.MinValue);
this.Text = Math.Round(result, this.DecimalPlaces).ToString("N" + this.DecimalPlaces);
}
else
{
try
{
//this.Text = Math.Min(this.MinValue, 0.0).ToString();
this.ClearValue(TextBox.TextProperty);
}
catch
{
}
}
if (ValueChanged != null)
ValueChanged(this, EventArgs.Empty);
}
}
答案 0 :(得分:1)
直接设置属性或调用ClearValue实际上会覆盖TextProperty上的任何内容,可能是BindingExpression。你真正想要做的只是设置价值,而不是真正改变那里的东西。听起来很混乱,整个DependencyProperty子系统都是。基本上将ClearValue替换为以下
this.SetValue(TextProperty, String.Empty)
您可以找到解释Introduction to Dependency Properties和Force a binding to update。两者都适用于WPF,但相关。但是UpdateTarget在Silverlight中不起作用(解决方案即将发布)。
那就是说,这种做法仍有缺陷。这就是你的源(你绑定的对象)仍然具有最新的有效值,即使根据你的UI值。要解决此问题,如果您使用的是WPF,则只需调用UpdateTarget即可从源获取最新的有效值并更新目标(文本框)。 Silverlight不支持这一点,但是有一种讨厌这种限制的方法:重新设置绑定。
代替ClearValue,您的代码将如下所示:
this.SetBinding(TextProperty, this.GetBindingExpression(TextProperty).ParentBinding);
if (double.TryParse(this.Text, out result))
{
result = Math.Min(result, this.MaxValue);
result = Math.Max(result, this.MinValue);
this.Text = Math.Round(result, this.DecimalPlaces).ToString("N" + this.DecimalPlaces);
}
最后一个块与方法的开头重复,因为我们可能需要在获得最新的有效值后重新格式化字符串。可能值得创建一种方法来实现这一目标。
希望这会有所帮助。
米格尔