Question

J'ai été sérieusement déçu du système de validation WPF. En tous cas! Comment puis-je valider le formulaire complet en cliquant sur le bouton "bouton"?

Pour une raison quelconque, tout dans WPF est tellement compliqué! Je peux faire la validation dans 1 ligne de code dans ASP.NET, ce qui nécessite environ 10 à 20 lignes de code dans WPF !!

Je peux le faire en utilisant mon propre framework ValidationEngine:

Customer customer = new Customer();
customer.FirstName = "John";
customer.LastName = String.Empty;

ValidationEngine.Validate(customer);

if (customer.BrokenRules.Count > 0)
{
   // do something display the broken rules! 
}
Était-ce utile?

La solution

Une application WPF doit désactiver le bouton permettant de soumettre un formulaire si les données saisies ne sont pas valides. Pour ce faire, vous pouvez implémenter l'interface IDataErrorInfo sur votre objet métier, à l'aide de liaisons avec ValidatesOnDataErrors = true . Pour personnaliser l'apparence des contrôles individuels en cas d'erreur, définissez un Validation.ErrorTemplate .

XAML:

<Window x:Class="Example.CustomerWindow" ...>
    <Window.CommandBindings>
        <CommandBinding Command="ApplicationCommands.Save"
                        CanExecute="SaveCanExecute"
                        Executed="SaveExecuted" />
    </Window.CommandBindings>
    <StackPanel>
        <TextBox Text="{Binding FirstName, ValidatesOnDataErrors=true, UpdateSourceTrigger=PropertyChanged}" />
        <TextBox Text="{Binding LastName, ValidatesOnDataErrors=true, UpdateSourceTrigger=PropertyChanged}" />
        <Button Command="ApplicationCommands.Save" IsDefault="True">Save</Button>
        <TextBlock Text="{Binding Error}"/>
    </StackPanel>
</Window>

Ceci crée une Fenêtre avec deux TextBox où vous pouvez éditer le prénom et le nom d'un client. Le " Enregistrer " Le bouton n'est activé que si aucune erreur de validation ne s'est produite. Le TextBlock situé sous le bouton indique les erreurs en cours pour que l'utilisateur sache ce qu'il se passe.

Le ErrorTemplate par défaut est une fine bordure rouge entourant le contrôle erroné. Si cela ne correspond pas à votre concept visuel, consultez la Validation dans Windows Presentation Foundation article sur CodeProject pour un examen approfondi de ce qui peut être fait à ce sujet.

Pour que la fenêtre fonctionne réellement, il doit y avoir une infrastructure un peu dans la fenêtre et le client.

code derrière

// The CustomerWindow class receives the Customer to display
// and manages the Save command
public class CustomerWindow : Window
{
    private Customer CurrentCustomer;
    public CustomerWindow(Customer c) 
    {
        // store the customer for the bindings
        DataContext = CurrentCustomer = c;
        InitializeComponent();
    }

    private void SaveCanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = ValidationEngine.Validate(CurrentCustomer);
    }

    private void SaveExecuted(object sender, ExecutedRoutedEventArgs e) 
    {
        CurrentCustomer.Save();
    }
}

public class Customer : IDataErrorInfo, INotifyPropertyChanged
{
    // holds the actual value of FirstName
    private string FirstNameBackingStore;
    // the accessor for FirstName. Only accepts valid values.
    public string FirstName {
        get { return FirstNameBackingStore; }
        set {
            FirstNameBackingStore = value;
            ValidationEngine.Validate(this);
            OnPropertyChanged("FirstName");
        }
    }
    // similar for LastName        

    string IDataErrorInfo.Error {
        get { return String.Join("\n", BrokenRules.Values); }
    }

    string IDataErrorInfo.this[string columnName]
    {
        get { return BrokenRules[columnName]; }
    }
}

Une amélioration évidente consisterait à déplacer l'implémentation IDataErrorInfo dans la hiérarchie des classes, car elle ne dépend que de ValidationEngine , mais pas de l'objet métier.

Bien qu’il s’agisse bien de plus de code que le simple exemple que vous avez fourni, il a également un peu plus de fonctionnalités que la simple vérification de la validité. Cela vous donne des informations précises et automatiquement mises à jour à l'utilisateur sur les problèmes de validation et désactive automatiquement l'option " Enregistrer " bouton tant que l'utilisateur tente de saisir des données non valides.

Autres conseils

Je suggérerais de regarder l'interface IDataErrorInfo sur votre objet métier. Consultez également cet article: Zone de texte à validation automatique

Vous êtes peut-être intéressé par l'exemple d'application BookLibrary du Framework d'application WPF ( WAF) . Il montre comment utiliser la validation dans WPF et comment contrôler le bouton Enregistrer en cas d'erreur de validation.

ValidatesOnDataError est utilisé pour valider les règles de gestion par rapport à vos modèles de vue. Il ne sera validé que si la liaison aboutit.

ValidatesOnExceptions doit être appliqué avec ValidatesOnDataError pour gérer les scénarios dans lesquels wpf ne peut pas effectuer de liaison en raison d'une incompatibilité de type de données. Supposons que vous souhaitiez lier un TextBox à la propriété Age (entier) dans votre modèle de vue

<TextBox Text="{Binding Age, ValidatesOnDataErrors=true, UpdateSourceTrigger=PropertyChanged}" />

Si l'utilisateur entre une entrée non valide en tapant des alphabets plutôt que des nombres en indiquant l'âge, par exemple xyz, la liaison de données wpf ignorera la valeur en silence car elle ne peut pas lier xyz à Age et l'erreur de liaison sera perdue à moins que la liaison ne soit décorée. ValidatesOnExceptions

<TextBox Text="{Binding Age, ValidatesOnDataErrors=true, ValidatesOnExceptions="True", UpdateSourceTrigger=PropertyChanged}" />

ValidatesOnException utilise la gestion des exceptions par défaut pour les erreurs de liaison à l'aide de ExceptionValidationRule, la syntaxe ci-dessus est une forme abrégée pour ce qui suit

<TextBox>
    <TextBox.Text>
        <Binding Path="Age" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">
            <Binding.ValidationRules>
                  <ExceptionValidationRule />
             </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

Vous pouvez définir vos propres règles à valider par rapport à l'entrée de l'utilisateur en dérivant de ValidationRule et en implémentant la méthode Validate, NumericRule dans l'exemple suivant

<TextBox.Text>
 <Binding Path="Age" ValidatesOnDataErrors="True">
   <Binding.ValidationRules>
        <rules:NumericRule />
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>

Les règles de validation doivent être génériques et non liées aux entreprises, car ces dernières sont accomplies via IDataErrorInfo et ValidatesOnDataError.

La syntaxe ci-dessus est assez compliquée comparée à la syntaxe de liaison à une ligne que nous avons. En mettant en oeuvre ValidationRule en tant que propriété attachée, la syntaxe peut être améliorée et vous pouvez la consulter ici

La description de votre problème est un peu vague pour moi. Je veux dire, je ne sais pas exactement quelle est votre difficulté. En supposant que le DataContext soit une sorte de présentateur ou de contrôleur ayant une propriété représentant l'instance du client, et ValidateCommand est une propriété de type ICommand:

  <StackPanel>  
    <TextBox Text="{Binding CurrentCustomer.FirstName}" />
    <TextBox Text="{Binding CurrentCustomer.LastName}" />
    <Button Content="Validate" 
            Command="{Binding ValidateCommand}"
            CommandParameter="{Binding CurrentCustomer}" />
    <ItemsControl ItemsSource="{Binding CurrentCustomer.BrokenRules}" />
  </StackPanel>

Ce XAML est vraiment simplifié, bien sûr, et il existe d’autres moyens de le faire. En tant que développeur Web très impliqué dans WPF, je trouve la plupart des tâches de ce type beaucoup plus simples dans WPF.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top