Правило проверки не обновляется корректно с двумя правилами проверки
Я просмотрел несколько постов, касающихся Правил валидации, но ужене сталкивался с проблемой, которую я испытываю.
Я использую правило проверки для текстового поля в окне WPF. У меня есть две проверки, одна для пустого текстового поля, а другая для недопустимых символов с использованием соответствия RegEx.
Моя проблема такая:
В моем текстовом поле:
Тип А - Работает, Отображает ничтоХит Backspace для пустой строки - Работает, отображает сообщение об ошибке проверки "Пожалуйста, введите значение во все поля "Тип ! - не работает - должно отображатьсяНеверные символы были найдены, но все равно отображаетПожалуйста, введите значение во все поля. "Backspace для пустой строки - Технически работает, потому что он по-прежнему отображает первую ошибку "Пожалуйста, введите значение во все поля. "Тип А - Работает, без сообщения об ошибкеТип ! - Хорошо, отображает сообщениеНеверные символы были найдены.То же самое происходит и наоборот.
Открытое окно
Тип ! - Отлично, отображаетНеверные символы были найдены.Backspace в пустую строку - все еще отображает "Неверные символы были найдены вместо "Пожалуйста, введите значение во все поля.Мой код выглядит следующим образом:
ProviderNew.xaml:
Код привилегии позади - ProviderNew.xaml.cs
public static readonly DependencyProperty NewProviderNameProperty = DependencyProperty.Register("ProviderName",
typeof (string), typeof(ProviderNew), new UIPropertyMetadata(""));
public string ProviderName
{
get { return (string) GetValue(NewProviderNameProperty); }
set { SetValue(NewProviderNameProperty, value); }
}
Класс преобразователя значений
public class ErrorsToMessageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var sb = new StringBuilder();
var errors = value as ReadOnlyCollection;
if (errors != null && errors.Count > 0)
{
foreach (var e in errors.Where(e => e.ErrorContent != null))
{
sb.AppendLine(e.ErrorContent.ToString());
}
}
return sb.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Класс провайдера
private string _providerName;
public string ProviderName
{
get { return _providerName; }
set
{
_providerName = value;
RaisePropertyChanged("ProviderName");
}
}
private void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Класс Правил валидации
public class ProviderValidation : ValidationRule
{
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
var str = value as string;
if (str != null && !Regex.IsMatch(str, @"^[a-zA-Z0-9]*$"))
{
return new ValidationResult(false, "Invalid characters were found.");
}
if (String.IsNullOrEmpty(str))
{
return new ValidationResult(false, "Please enter a value in all fields.");
}
return new ValidationResult(true, null);
}
}
Я попытался установить события LostFocus и TextChanged для принудительного обновления, используя:
var expression = txtBoxProviderName.GetBindingExpression(TextBox.TextProperty);
if (expression != null)
expression.UpdateSource();
Установка точек останова в методе Validate показывает, что правильные совпадения выполнены и возвращается правильный ValidationResult, но он не обновляет текст корректно.
Я делаю что-то невероятно глупое?
Любые предложения будут оценены.
Редактировать 1.
Да, у меня это работает, используя MultiDataTrigger и Binding к текстовым полям.
Что неЭто когда я впервые показываю окно, кнопка включена, что я неЭто не должно быть, потому что это может позволить пользователю нажать кнопку «Сохранить» с пустыми текстовыми полями.
Правило валидациине работает прямо с самого начала, когда открывается окно.
Я установил фокус на текстовое поле, и если оно теряет фокус или вводятся неверные данные, то запускается правило проверки и отключается кнопка.
Установка кнопки отключенной по умолчанию, делает ее отключенной при открытии, но тогда это неt включается, когда нет ошибок валидации.
Я могу заставить его работать, принудительно проверив правило валидации, скажем, на событии Load, используя
var expression = txtBoxProviderName.GetBindingExpression(TextBox.TextProperty);
if (expression != null)
expression.UpdateSource();
Но затем, когда впервые открывается окно, оно сразу показывает сообщение об ошибке проверки »Пожалуйста, введите значение во все поля "что я немне очень нравится внешний вид.
В любом случае, или я не могу иметь лучшее из обоих миров.
Вот код кнопки
Спасибо,
Neill
Редактировать 2
Быстрый вопрос Я не могнайти пространство имен RelayCommand. В поисках другого кода я нашел пример MVVM от Microsoft, который реализует класс RelayCommand: ICommand.
Это правильно?
Код является:
public class RelayCommand : ICommand
{
#region Fields
readonly Action _execute;
readonly Predicate _canExecute;
#endregion // Fields
#region Constructors
///
/// Creates a new command that can always execute.
///
/// The execution logic.
public RelayCommand(Action execute)
: this(execute, null)
{
}
///
/// Creates a new command.
///
/// The execution logic.
/// The execution status logic.
public RelayCommand(Action execute, Predicate canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion // ICommand Members
}
Я реализовал следующее в моем ProviderNew.xaml.cs:
private ICommand saveCommand;
public ICommand SaveCommand
{
get
{
if (saveCommand == null)
{
saveCommand = new RelayCommand(p => DoSave(), p => CanSave() );
}
return saveCommand;
}
}
private bool CanSave()
{
if (!string.IsNullOrEmpty(ProviderName))
{
??? What goes here?
}
return true;
}
private bool DoSave()
{
// Save the information to DB
}
Честно говоря, я не уверен, что должно быть закодировано в блоке вif (! string.IsNullOrEmpty (ProviderName)) '
Кроме того, вы сказали добавить код ICommand в DataContext, поэтому не уверены, что он находится в нужном месте, потому что когда я открываю окно, сохранение активируется, и нажатие на него ничего не дает, даже если во всех полях содержатся правильные данные.
Вот код ProviderNew xaml для кнопки
Ваша помощь очень ценится.
С Уважением,
Neill