2012-01-26 3 views
1

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

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

Я имею в виду эти процессы:

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}}" 
+0

Покажите нам код, который вы используете для привязки текстовых полей. – gabsferreira

+0

@devGabriel обновлен! –

ответ

3

Вы используете 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 
} 
+0

Последнее утверждение имеет смысл. Итак, как вы думаете, удобно использовать что-то вроде конвертера? –

+0

@DarfZon Для чего? Конвертеры предназначены для преобразования одного типа данных в другой, поэтому я не вижу, что вы пытаетесь выполнить с помощью одного. – Rachel

+0

Хорошо, одно сомнение. В этом случае, как я могу использовать IDataErrorInfo, потому что, если я установил вручную значение null для свойства Number, textBox будет обновлять (и должен показывать неправильное значение) –

0

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

Примером реализации этого может идти следующим образом:

<...> 
    <Binding.ValidationRules> 
    <ExceptionValidationRule /> 
    </Binding.ValidationRules> 
</...> 

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

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

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

+0

Я не знаю, как это может мне помочь. Я действительно использую правила valdation с этим атрибутом: ValidatesOnExceptions = True –

1

Я думаю, что самый простой способ получить такое поведение является использование 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

Для этого вам нужно будет поместить свою логику в 'ConvertBack', так как это происходит при попытке обновить свойство, поддерживающее привязку, и я не думаю, что он покажет ошибки проверки. – Rachel

+0

@Rachel хорошая точка в направлении преобразования, и вы правы: он не будет показывать ошибки проверки, поскольку больше не будет никаких ошибок проверки - каждое значение, установленное для свойства, будет действительным. OP не упоминает сообщения о проверке, поэтому я предполагаю, что это нормально –

+0

Я предположил, что он заботился о валидации, поскольку привязка содержала 'ValidatesOnDataErrors =" True "', но если это не так, и если ему было все равно, что текст TextBox сбрасывается, когда вводится недопустимое значение, тогда это, вероятно, будет работать нормально. Я думаю. Я бы хотел проверить это, потому что «null» является допустимым значением для объекта данных, но не для конвертера :) – Rachel

Смежные вопросы