Utiliser les règles de Validation WPF et désactiver le bouton "Enregistrer"

j'ai une page où quelques boîtes 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 boîte de texte jusqu'à ce que j'entre une valeur. Donc 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 n'ait aucune erreur? Je ne sais pas quoi vérifier pour voir si il y a des erreurs de validation.

27
demandé sur Dave Clemmer 2008-10-23 23:13:54

8 réponses

sur le codebehind pour la vue, vous pouvez ajouter la validation.ErrorEvent comme suit:

this.AddHandler(Validation.ErrorEvent,new RoutedEventHandler(OnErrorEvent)); 

Et

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;
}

ceci fait l'hypothèse que vous recevrez un avis de suppression (ce qui n'arrivera pas si vous supprimez l'élément offensant pendant qu'il est invalide).

15
répondu Christoph 2009-04-30 22:56:16

Vous souhaitez utiliser Validation.HasError propriété attachée.

dans le même ordre d'idées, Josh Smith a une lecture intéressante sur Liaison d' (Validation.Erreurs)[0] sans créer Debug Spew.

8
répondu Todd White 2008-10-24 05:22:40
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;
    }
}
3
répondu Nihal 2011-09-22 11:53:36

Voici une méthode helper qui trace les erreurs de validation sur les objets de dépendances (et tous ses enfants) et appelle delegate pour notifier le changement. Il suit également l'enlèvement 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);
        } 
2
répondu andrey.tsykunov 2011-11-16 19:50:20

c'est ça vous devez vérifier la propriété de contrôle HasError à partir du code behaind

et faire ce code dans le bouton enregistrer, cliquez sur

 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());
2
répondu Bilal 2012-12-25 11:36:08

il suffit d'insérer votre modèle de vue du système.ComponentModel.IDataErrorInfo pour valider et de INotifyPropertyChanged pour notifier le bouton

faire de la propriété:

    public bool IsValid
    {
        get
        {
            if (this.FloorPlanName.IsEmpty())
                return false;
            return true;
        }
    }

dans le code xaml, le connecter à bouton

<Button Margin="4,0,0,0" Style="{StaticResource McVMStdButton_Ok}" Click="btnDialogOk_Click" IsEnabled="{Binding IsValid}"/>

dans les dérogations 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;
            }
        }
}
1
répondu Alexander Sirotkin 2014-11-21 11:47:23

j'ai essayé plusieurs des solutions mentionnées ci-dessus; cependant, aucune d'entre elles n'a fonctionné pour moi.

Mon Problème Simple

j'ai une fenêtre de saisie simple qui demande un URI de l'utilisateur, si le TextBox valeur n'est pas valide Uri puis Okay bouton doit être désactivé.

Ma Solution Simple

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)));
1
répondu Kabuo 2016-01-22 18:42:44