Создание пустого поля Silverlight 4 Custom NumberBox без очистки привязки - PullRequest
0 голосов
/ 26 января 2012

Я пытаюсь создать свой собственный очень простой NumberBox, унаследованный от TextBox, который проверяет ввод на потерянном фокусе и форматирует значение на основе указанных десятичных разрядов. Все работает хорошо, пока кто-то не выставит какое-то неверное значение.

В случае недопустимого значения, я бы хотел, чтобы 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 Ответ

1 голос
/ 26 января 2012

Установка свойства напрямую или вызов ClearValue фактически переопределяет все, что находится в TextProperty, что может быть выражением BindingExpression. То, что вы действительно хотите сделать, это просто установить значение, не меняя при этом то, что там есть. Звучит запутанно и вся подсистема DependencyProperty есть. В основном замените ClearValue на следующее

this.SetValue(TextProperty, String.Empty)

Вы можете найти объяснение Введение в свойства зависимостей и Принудительная привязка для обновления . Оба для WPF, но актуальны. UpdateTarget не работает в Silverlight, хотя (решение приходит).

Тем не менее, этот подход все еще имеет недостаток. Дело в том, что ваш источник (объект, к которому вы привязываете) будет по-прежнему иметь последнее действительное значение, даже если в соответствии с вашим пользовательским интерфейсом оно равно. Чтобы это исправить, если вы были в 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);
}

Последний блок дублируется с началом вашего метода, поскольку нам может потребоваться переформатировать строку после того, как мы получим последнее допустимое значение. Возможно, стоит создать метод для этого.

Надеюсь, это поможет.

Miguel

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...