J'ai une page où quelques zones de texte ne peuvent pas être vides avant de cliquer sur un bouton Enregistrer.
<TextBox...
<TextBox.Text>
<Binding Path ="LastName" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:StringRequiredValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
Ma règle fonctionne. J'ai une bordure rouge autour de ma zone de texte jusqu'à ce que j'entre une valeur. Alors maintenant, je veux ajouter cette règle de validation à mes autres zones de texte.
Maintenant, comment désactiver le bouton Enregistrer jusqu'à ce que la page ne contienne aucune erreur? Je ne sais pas quoi vérifier pour voir s'il y a des erreurs de validation.
Voici l'exemple complet dont vous avez besoin.
http://codeblitz.wordpress.com/2009/05/08/wpf-validation-made-easy-with-idataerrorinfo/
https://skydrive.live.com/?cid=2c6600f1c1d5e3be&id=2C6600F1C1D5E3BE%212
Sur le codebehind pour la vue, vous pouvez câbler le Validation.ErrorEvent comme ceci;
this.AddHandler(Validation.ErrorEvent,new RoutedEventHandler(OnErrorEvent));
Puis
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;
}
Cela suppose que vous serez averti de la suppression (ce qui ne se produira pas si vous supprimez l'élément incriminé alors qu'il n'est pas valide).
Vous souhaitez utiliser Validation.HasError propriété jointe.
Dans le même ordre d'idées, Josh Smith a une lecture intéressante sur Binding to (Validation.Errors) [0] sans création de débogage .
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;
}
}
Voici une méthode d'assistance qui suit les erreurs de validation sur les objets de dépendance (et tous ses enfants) et appelle délégué pour informer de la modification. Il suit également la suppression des enfants avec des erreurs de validation.
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);
}
c'est ce dont vous avez besoin pour vérifier la propriété de contrôle HasError à partir du code derrière
et faites ce code dans le bouton Enregistrer cliquez
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());
J'ai essayé plusieurs des solutions indiquées ci-dessus; cependant, aucun d'entre eux n'a travaillé pour moi.
J'ai une fenêtre d'entrée simple qui demande un URI à l'utilisateur, si la valeur TextBox
n'est pas un Uri
valide, alors le bouton Okay
doit être désactivé.
Voici ce qui a fonctionné pour moi:
CommandBindings.Add(new CommandBinding(AppCommands.Okay,
(sender, args) => DialogResult = true,
(sender, args) => args.CanExecute = !(bool) _uriTextBoxControl.GetValue(Validation.HasErrorProperty)));
héritez juste de votre ViewModel de System.ComponentModel.IDataErrorInfo pour Validate et de INotifyPropertyChanged pour notifier le bouton
faire une propriété:
public bool IsValid
{
get
{
if (this.FloorPlanName.IsEmpty())
return false;
return true;
}
}
en xaml, connectez-le au bouton
<Button Margin="4,0,0,0" Style="{StaticResource McVMStdButton_Ok}" Click="btnDialogOk_Click" IsEnabled="{Binding IsValid}"/>
dans les remplacements IDataErrorInfo, notifiez 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;
}
}
}
Parce qu'il est toujours manquant, voici une adaptation de la réponse du développeur au cas où le lien disparaîtrait:
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/C #:
private int _numberOfValidationErrors;
public bool HasNoValidationErrors => _numberOfValidationErrors = 0;
private void handleValidationError(object sender, ValidationErrorEventArgs e)
{
if (e.Action == ValidationErrorEventAction.Added)
_numberOfValidationErrors++;
else
_numberOfValidationErrors--;
}