Ответ 1
Вот полный пример того, что вам нужно.
http://codeblitz.wordpress.com/2009/05/08/wpf-validation-made-easy-with-idataerrorinfo/
https://skydrive.live.com/?cid=2c6600f1c1d5e3be&id=2C6600F1C1D5E3BE%21203
У меня есть страница, где несколько текстовых полей не могут быть пустыми, прежде чем нажать кнопку "Сохранить".
<TextBox...
<TextBox.Text>
<Binding Path ="LastName" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:StringRequiredValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
Мое правило работает. У меня есть красная рамка вокруг моего текстового поля, пока я не введу значение. Поэтому теперь я хочу добавить это правило проверки в другие текстовые поля.
Теперь, как отключить кнопку "Сохранить", пока страница не будет иметь ошибок? Я не знаю, что проверить, есть ли ошибки проверки.
Вот полный пример того, что вам нужно.
http://codeblitz.wordpress.com/2009/05/08/wpf-validation-made-easy-with-idataerrorinfo/
https://skydrive.live.com/?cid=2c6600f1c1d5e3be&id=2C6600F1C1D5E3BE%21203
В коде для представления вы можете подключить Validation.ErrorEvent так:
this.AddHandler(Validation.ErrorEvent,new RoutedEventHandler(OnErrorEvent));
И затем
private int errorCount;
private void OnErrorEvent(object sender, RoutedEventArgs e)
{
var validationEventArgs = e as ValidationErrorEventArgs;
if (validationEventArgs == null)
throw new Exception("Unexpected event args");
switch(validationEventArgs.Action)
{
case ValidationErrorEventAction.Added:
{
errorCount++; break;
}
case ValidationErrorEventAction.Removed:
{
errorCount--; break;
}
default:
{
throw new Exception("Unknown action");
}
}
Save.IsEnabled = errorCount == 0;
}
Это делает предположение, что вы получите уведомление об удалении (что не произойдет, если вы удалите оскорбительный элемент, пока он недействителен).
Вы хотите использовать прикрепленное свойство Validation.HasError.
В то же самое время Джош Смит интересен, прочитав привязка к (Validation.Errors) [0] без создания отладки отладки.
int count = 0;
private void LayoutRoot_BindingValidationError(object sender, ValidationErrorEventArgs e)
{
if (e.Action == ValidationErrorEventAction.Added)
{
button1.IsEnabled = false;
count++;
}
if (e.Action == ValidationErrorEventAction.Removed)
{
count--;
if (count == 0) button1.IsEnabled = true;
}
}
Вот вспомогательный метод, который отслеживает ошибки проверки на объектах зависимостей (и всех его дочерних элементах) и вызывает делегат для уведомления об изменении. Он также отслеживает удаление детей с ошибками проверки.
public static void AddErrorHandler(DependencyObject element, Action<bool> setHasValidationErrors)
{
var errors = new List<Tuple<object, ValidationError>>();
RoutedEventHandler sourceUnloaded = null;
sourceUnloaded = (sender, args) =>
{
if (sender is FrameworkElement)
((FrameworkElement) sender).Unloaded -= sourceUnloaded;
else
((FrameworkContentElement) sender).Unloaded -= sourceUnloaded;
foreach (var error in errors.Where(err => err.Item1 == sender).ToArray())
errors.Remove(error);
setHasValidationErrors(errors.Any());
};
EventHandler<ValidationErrorEventArgs> errorHandler = (_, args) =>
{
if (args.Action == ValidationErrorEventAction.Added)
{
errors.Add(new Tuple<object, ValidationError>(args.OriginalSource, args.Error));
if (args.OriginalSource is FrameworkElement)
((FrameworkElement)args.OriginalSource).Unloaded += sourceUnloaded;
else if (args.OriginalSource is FrameworkContentElement)
((FrameworkContentElement)args.OriginalSource).Unloaded += sourceUnloaded;
}
else
{
var error = errors
.FirstOrDefault(err => err.Item1 == args.OriginalSource && err.Item2 == args.Error);
if (error != null)
errors.Remove(error);
}
setHasValidationErrors(errors.Any());
};
System.Windows.Controls.Validation.AddErrorHandler(element, errorHandler);
}
вот оно вам нужно проверить свойство управления HasError из кода behaind
и сделайте этот код в кнопке сохранения нажмите
BindingExpression bexp = this.TextBox1.GetBindingExpression(TextBox.TextProperty);
bexp.UpdateSource(); // this to refresh the binding and see if any error exist
bool hasError = bexp.HasError; // this is boolean property indique if there is error
MessageBox.Show(hasError.ToString());
просто наследует ваш ViewModel из System.ComponentModel.IDataErrorInfo для проверки и из кнопки INotifyPropertyChanged для уведомления
Сделать свойство:
public bool IsValid
{
get
{
if (this.FloorPlanName.IsEmpty())
return false;
return true;
}
}
в xaml, подключите его к кнопке
<Button Margin="4,0,0,0" Style="{StaticResource McVMStdButton_Ok}" Click="btnDialogOk_Click" IsEnabled="{Binding IsValid}"/>
в переопределении IDataErrorInfo, уведомить btutton
public string this[string columnName]{
get
{
switch (columnName)
{
case "FloorPlanName":
if (this.FloorPlanName.IsEmpty())
{
OnPropertyChanged("IsValid");
return "Floor plan name cant be empty";
}
break;
}
}
}
Я пробовал несколько решений, указанных выше; однако никто из них не работал у меня.
У меня есть простое окно ввода, которое запрашивает URI от пользователя, если значение TextBox
не является допустимым Uri
, тогда кнопка Okay
должна быть отключена.
Вот что сработало для меня:
CommandBindings.Add(new CommandBinding(AppCommands.Okay,
(sender, args) => DialogResult = true,
(sender, args) => args.CanExecute = !(bool) _uriTextBoxControl.GetValue(Validation.HasErrorProperty)));
Поскольку это все еще отсутствует, вот адаптация ответа Разработчика в случае, если ссылка когда-либо исчезнет:
XAML:
<TextBox.Text Validation.Error="handleValidationError">
<Binding Path ="LastName"
UpdateSourceTrigger="PropertyChanged"
NotifyOnValidationError="True">
<Binding.ValidationRules>
<local:StringRequiredValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
<Button IsEnabled="{Binding HasNoValidationErrors}"/>
CodeBehind/С#:
private int _numberOfValidationErrors;
public bool HasNoValidationErrors => _numberOfValidationErrors = 0;
private void handleValidationError(object sender, ValidationErrorEventArgs e)
{
if (e.Action == ValidationErrorEventAction.Added)
_numberOfValidationErrors++;
else
_numberOfValidationErrors--;
}