Как установить нулевое значение для свойства, когда оно выдает ошибку? - PullRequest
1 голос
/ 26 января 2012

Связывание является настолько мощным в WPF. Предположим, что у нас есть свойство Number (nullable int) и оно связано с текстовым полем.

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

Я имею в виду следующие процессы:

TEXTBOX: ""     PROPERTY: null
TEXTBOX: "2"    PROPERTY: 2
TEXTBOX: "2b"   PROPERTY: 2   <-- here is the problem, should be null instead 2(by the error)

Есть ли способ, которым привязка устанавливает нулевое значение при возникновении ошибки?

Некоторые люди говорили мне, что мне нужно реализовать IDataErrorInfo, но я полагаю, что этот интерфейс предназначен для проверки бизнес-правил. Так что я бы не предпочел пользователя.

UPDATE:

    <TextBox Text="{Binding Number, UpdateSourceTrigger=PropertyChanged,
        ValidatesOnExceptions=True, ValidatesOnDataErrors=True,
        NotifyOnValidationError=True, TargetNullValue={x:Static sys:String.Empty}}"

Ответы [ 3 ]

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

Вы используете UpdateSourceTrigger=PropertyChanged, что означает, что каждый раз, когда пользователь нажимает клавишу, он сохраняет данные в контексте данных

Например, пользователь вводит 2, тогда ваша собственность равна "2". Пользователь вводит b, и он пытается заменить "2" на "2b", что не удается, поэтому первоначальное свойство "2" остается.

Удалите UpdateSourceTrigger, и он вернется к значению по умолчанию LostFocus, что означает, что он будет обновлять свойство только тогда, когда TextBox теряет фокус.

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

В качестве примечания используйте IDataErrorInfo для всей проверки, а не только для проверки бизнес-правил. WPF создан для работы с ним. Мои модели используют его для проверки правильности длины, типа и т. Д., А мои ViewModels используют его для проверки соблюдения бизнес-правил

Редактировать

Альтернативное предложение, которое у меня было бы, - привязать к строковому значению, а не к числовому полю. Таким образом, когда значение изменяется, вы можете попробовать привести его к вашему Int и вернуть ошибку, если оно не может быть приведено.

public class SomeObject : IDataErrorInfo
{
    public string SomeString { get; set; }
    public Int32? SomeNumber { get; set; }

    #region IDataErrorInfo Members

    public string Error
    {
        get { throw new NotImplementedException(); }
    }

    public string this[string columnName]
    {
        get
        {
            if (columnName == "SomeString")
            {
                int i;
                if (int.TryParse(SomeString, i))
                {
                    SomeNumber = i;
                }
                else
                {
                    SomeNumber = null;
                    return "Value is not a valid number";
                }
            }
            return null;
        }
    }

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

Я думаю, что самый простой способ получить такое поведение - использовать IValueConverter для преобразования из string в int?:

public class NullableIntConverter : IValueConverter
{
    public static NullableIntConverter Instance = new NullableIntConverter();
    public void ConvertBack(object value, ...)
    {
        int intValue = 0;
        if (int.TryParse((string)value, out intValue))
            return intValue;

        return null;
    }

    public void Convert(object value, ...)
    {
        return value.ToString();
    }
}

Затем вы можете указать это в привязке, как показано ниже (где local сопоставлено с пространством имен вашего конвертера):

<TextBox Text="{Binding Number, Converter="{x:Static local:NullableIntConverter.Instance}" ... />
0 голосов
/ 26 января 2012

Становится еще мощнее.Вероятно, вам следует пройти путь проверки через сам интерфейс / привязку - WPF имеет встроенную поддержку для этого, примеры которой можно найти в Обзоре привязки данных в MSDN .

*.1004 * Пример реализации этого может выглядеть следующим образом:
<...>
  <Binding.ValidationRules>
    <ExceptionValidationRule />
  </Binding.ValidationRules>
</...>

Связанная документация охватывает немало вопросов по теме связывания, поэтому вот выдержка из соответствующего раздела «Проверка данных»:

Объект ValidationRule проверяет, является ли значение свойства допустимым.

A ExceptionValidationRule проверяет исключения, возникающие при обновлении свойства источника привязки.В предыдущем примере StartPrice имеет тип integer.Когда пользователь вводит значение, которое не может быть преобразовано в целое число, возникает исключение, в результате чего привязка помечается как недействительная.Альтернативный синтаксис для явной установки ExceptionValidationRule - установить для свойства ValidatesOnExceptions значение true для объекта Binding или MultiBinding.

...