使Silverlight 4自定义数字框空白而不清除绑定

时间:2012-01-26 04:08:36

标签: silverlight silverlight-4.0 custom-controls

我正在尝试创建自己非常简单的继承自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); 
        }
    }

1 个答案:

答案 0 :(得分:1)

直接设置属性或调用ClearValue实际上会覆盖TextProperty上的任何内容,可能是BindingExpression。你真正想要做的只是设置价值,而不是真正改变那里的东西。听起来很混乱,整个DependencyProperty子系统都是。基本上将ClearValue替换为以下

this.SetValue(TextProperty, String.Empty)

您可以找到解释Introduction to Dependency PropertiesForce 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);
}

最后一个块与方法的开头重复,因为我们可能需要在获得最新的有效值后重新格式化字符串。可能值得创建一种方法来实现这一目标。

希望这会有所帮助。

米格尔