Microsoft-ui-xaml: Ajouter la prise en charge de la validation des entrées à UWP avec INotifyDataErrorInfo

Créé le 14 janv. 2019  ·  50Commentaires  ·  Source: microsoft/microsoft-ui-xaml

Proposition : ajouter la prise en charge de la validation des entrées avec INotifyDataErrorInfo

Résumé

Ajoutez la prise en charge de la validation d'entrée avec INotifyDataErrorInfo qui est pris en charge par x:Bind et Binding. Les deux extensions de balisage doivent obtenir une nouvelle propriété ValidatesOnNotifyDataErrors qui est - comme dans la liaison de WPF - vraie par défaut.

Raisonnement

Actuellement, UWP n'a pas de validation d'entrée intégrée à la plate-forme. Mais chaque application métier nécessite une validation des entrées. C'est l'une des fonctionnalités les plus importantes pour une application d'entreprise appropriée. Il y a une entrée sur uservoice qui dit que cette fonctionnalité viendra avec WinUI, mais je n'ai encore rien vu : https://wpdev.uservoice.com/forums/110705-universal-windows-platform/suggestions/13052589-uwp-input -validation

feature proposal needs-winui-3 team-Markup

Commentaire le plus utile

INDEI vous demande de mettre en place toutes vos entités et sous entités.

Pouvez-vous en dire plus ?

En utilisant des règles, aucune modification n'est requise, tout fonctionne automatiquement en utilisant uniquement les attributs de validation.

Pour la plupart, tout fonctionne automatiquement lorsque vous utilisez ValidationAttributes et INotifyDataErrorInfo également. Je vais montrer ici quelques extraits de code qui sont dans la spécification, juste pour que nous soyons (espérons-le) sur la même page.

FWIW, nous prévoyons d'avoir cette classe ValidationBase dans la boîte à outils, vous n'avez donc pas à écrire vous-même ce code passe-partout.

public class ValidationBase : INotifyPropertyChanged, INotifyDataErrorInfo
{
   public event PropertyChangedEventHandler PropertyChanged;
   public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

   protected void SetValue<T>(ref T currentValue, T newValue, [CallerMemberName] string propertyName = "")
   {
       if (!EqualityComparer<T>.Default.Equals(currentValue, newValue))
       {
           currentValue = newValue;
           OnPropertyChanged(propertyName, newValue);
       }
   }

   readonly Dictionary<string, List<ValidationResult>> _errors = new Dictionary<string, List<ValidationResult>>();
   public bool HasErrors
   {
       get
       {
           return _errors.Any();
       }
   }
   public IEnumerable GetErrors(string propertyName)
   {
       return _errors[propertyName];
   }

   private void OnPropertyChanged(string propertyName, object value)
   {
       PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
       Validate(propertyName, value);
   }

   private void AddErrors(string propertyName, IEnumerable<ValidationResult> results)
   {
       if (!_errors.TryGetValue(propertyName, out List<ValidationResult> errors))
       {
           errors = new List<ValidationResult>();
           _errors.Add(propertyName, errors);
       }

       errors.AddRange(results);
       ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
   }

   private void ClearErrors(string propertyName)
   {
       if (_errors.TryGetValue(propertyName, out List<ValidationResult> errors))
       {
           errors.Clear();
           ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
       }
   }

   public void Validate(string memberName, object value)
   {
       ClearErrors(memberName);
       List<ValidationResult> results = new List<ValidationResult>();
       bool result = Validator.TryValidateProperty(
            value,
            new ValidationContext(this, null, null)
            {
                MemberName = memberName
            },
            results
            );

        if (!result)
        {
            AddErrors(memberName, results);
        }
    }
}

Votre modèle dériverait alors de cette classe et ressemblerait à ceci :

public class Person : ValidationBase
{
    private string name;
    [MinLength(4)]
    [MaxLength(6)]
    public string Name
    {   
        get { return name; }
        set { SetValue(ref name, value); }
    }
}

En supposant que cette classe Person est définie sur une propriété ViewModel sur votre Page , vous vous liez ensuite à celle-ci et la validation se produit automatiquement :

<TextBox Text="{x:Bind ViewModel.Name, Mode=TwoWay}" />

Je comprends que cela puisse être un peu différent de ce que vous faites aujourd'hui, mais nous essayons de ne pas soutenir deux façons différentes de faire la même chose si nous n'en avons pas besoin. Faites-moi savoir si cela a du sens, ou si vous pensez qu'il nous manque encore quelque chose !

Tous les 50 commentaires

@LucasHaines, quel est le lien avec les fonctionnalités de validation des entrées que vous avez étudiées ?

@jevansaks Ceci est directement lié au travail de validation des entrées que je décris.

Super. Si vous avez des aperçus à partager, je serai ravi de les essayer et de vous faire part de vos commentaires et de vos réflexions.

image

C'est le type de validation mentionné lors de la construction 2018

`
x:Name="UserName" Header="Nom d'utilisateur :"
Text="{x : lier ViewModel.Person.UserName,
UpdateSourceTrigger=PropertyChanged,
Mode=Bidirectionnel}" />

x:Name="Mot de passe" Header="Mot de passe :"
Password="{x : lier ViewModel.Person.Password,
UpdateSourceTrigger=LostFocus,
Mode=Bidirectionnel}"/>
`

@thomasclaudiushuber à quel point pensez-vous que ce travail est important dans le cadre de {Binding} ? Je demande seulement parce que les défis techniques là-bas ne sont pas triviaux, ainsi que le fait qu'il ne peut pas fonctionner à un niveau inférieur. Notre idée originale était de simplement prendre en charge x:Bind, qui ne nécessitera que des modifications du compilateur de balisage et est capable de fonctionner de bas niveau.

De plus, nous prévoyions uniquement de prendre en charge le paradigme INotifyDataErrorInfo et DataAnnotations. Nous n'avions pas l'intention d'ajouter quelque chose d'analogue à Binding.ValidationRules, et nous n'avons donc pas estimé qu'il y avait un besoin suffisant pour un ValidatesOnNotifyDataErrors.

Nous serions ravis de recevoir vos commentaires alors que nous continuons à travailler sur cette fonctionnalité afin que cela puisse être fait correctement !

@stevenbrix

Réponse courte : oui, ce que vous pensez et ce que vous prévoyez semble très bien. Juste x:Bind va bien, et juste INotifyDataErrorInfo va bien aussi.

Long:

Juste x : lier ? 👍

Dans tous les cas WPF-LOB auxquels je peux penser, il y avait toujours une sorte de ViewModel qui était connue au moment de la compilation, pas de typage de canard, donc x:Bind va bien. J'ai également écrit {Binding} dans ce numéro car je pensais que vous pouviez le prendre en charge pour obtenir la même syntaxe que dans WPF. Mais c'est plus « agréable à avoir » que super important. Et comme {Binding} et x:Bind sont deux choses complètement différentes dans les coulisses et que les éléments d'exécution avec {Binding} ne sont pas triviaux comme vous l'avez mentionné, oubliez {Binding}. Je pense que l'avoir juste pour x:Bind est tout à fait bien, cela fonctionnera pour les cas d'utilisation auxquels je peux penser. Et d'après toutes les conférences que j'ai faites sur UWP et x:Bind, je peux vous dire que x:Bind est l'une des fonctionnalités UWP les plus préférées de tous les développeurs XAML et je leur ai dit à tous "Préférez x:Bind à Binding partout où vous pouvez". :) Obtenir des erreurs intellisense, perf, step-into-code et compile-time fait de x:Bind la nouvelle valeur par défaut sur UWP, donc avoir le support de validation juste là est bien et une bonne décision imo.

Juste le paradigme INotifyDataErrorInfo et DataAnnotations ? 👍

Le simple fait de prendre en charge le paradigme INotifyDataErrorInfo et DataAnnotations me semble bon. WPF ne récupère pas automatiquement les annotations de données, vous devez les connecter manuellement dans votre implémentation INotifyDataErrorInfo en utilisant la classe Validator. Vous voulez dire cela quand vous dites "paradigme DataAnnotations", n'est-ce pas ? Ou prévoyez-vous une prise en charge intégrée de DataAnnotation qui permet à un développeur de simplement mettre une annotation de données sur une propriété et cela fonctionne ? Comme dans ASP.NET Core MVC ? Bien que ce serait formidable, je pense que ce n'est pas nécessaire. Avoir les classes ValidationContext, Validator et ValidationResult et les autres classes de System.ComponentModel.DataAnnotations est suffisant imo.

Ajouter Binding.ValidationRules ? Noooooon ;-)

Non, n'ajoutez surtout pas ça. INotifyDataErrorInfo est suffisant et c'est le meilleur. Je pense que je n'ai plus jamais utilisé ValidationRules après l'ajout du support IDataErrorInfo à WPF (si je me souviens bien, c'était dans .NET Framework 3.5). Et lorsque INotifyDataErrorInfo a été ajouté dans .NET Framework 4.5, mes clients et moi avons utilisé cette interface dans tous les projets pour la validation des entrées. Prendre en charge uniquement cette interface est très bien.

Ajouter ValidatesOnNotifyDataErrors ? Non mais...

Oui, vous n'avez pas à ajouter celui-ci. Mais cela n'a rien à voir avec les Binding.ValidationRules. Cette propriété est directement liée à l'interface INotifyDataErrorInfo. Sur l'extension de balisage de liaison de WPF, ValidatesOnNotifyDataErrors est vrai par défaut, ce qui signifie que {Binding} récupère la validation INotifyDataErrorInfo implémentée si l'objet lié implémente cette interface. Si vous définissez la propriété ValidatesOnNotifyDataErrors sur l'extension de balisage de liaison sur false, l'extension de balisage de liaison ne récupère pas l'implémentation INotifyDataErrorInfo pour la validation. Donc, peut-être que ce n'est pas trop difficile à implémenter avec x:Bind, mais peut-être que nous n'en avons pas besoin. Alors, non, ne le fais pas. C'est ok de laisser ça de côté. Mais permettez-moi de décrire le scénario où j'avais besoin de cela dans le passé :

Les contrôles WPF affichent par défaut une bordure rouge définie via Validation.ErrorTemplate. Supposons maintenant que vous ayez une implémentation INotifyDataErrorInfo avec une classe qui a la propriété FirstName. Elle est obligatoire, vous renvoyez donc une erreur si la propriété FirstName est nulle ou vide. Maintenant, vous avez lié un TextBox à cette propriété FirstName. Lorsqu'un utilisateur supprime ce prénom, une bordure rouge apparaît. Super, exactement ce que tu veux. Mais peut-être avez-vous à un autre endroit de l'interface utilisateur un autre contrôle lié à la propriété FirstName également. Par exemple un TextBlock dans un Tab-Header. WPF affichera également sur ce TextBlock une bordure rouge en cas d'erreur de validation. Mais ce n'est peut-être pas ce que vous voulez. Vous voulez l'erreur juste sur le TextBox où l'utilisateur peut changer le prénom, mais pas dans le TextBlock dans l'en-tête de l'onglet. Pour vous débarrasser de la bordure rouge sur le TextBlock, vous n'avez pas besoin de modifier le ErrorTemplate du TextBlock, à la place, vous désactivez simplement la validation INotifyDataErrorInfo sur le TextBlock-FirstName-Binding en définissant la propriété ValidatesOnNotifyDataErrors sur false. C'est le seul et unique cas d'utilisation que j'ai jamais eu pour cette propriété. :)

J'espère que ça aide.

Résumé

Oui, je suis totalement d'accord, avoir une validation d'entrée uniquement sur x:Bind avec prise en charge de INotifyDataErrorInfo est un bon plan.

Non, c'est un plan fantastique, je suis déjà super excitée !

@thomasclaudiushuber merci pour le suivi détaillé ! Les scénarios de base que vous décrivez correspondent à ce que nous pensions être le véritable moteur de valeur, et c'est donc bon à entendre. La conception globale de cette fonctionnalité et de l'API a évolué, principalement en raison des travaux antérieurs de WPF. Il y avait quelques choses importantes à appeler ici:

  1. Comme indiqué ci-dessus, il y avait certains aspects du système de validation de WPF qui, selon nous, n'avaient aucune valeur ajoutée, ou ont été remplacés par de meilleurs modèles, et nous n'avions donc pas l'intention de les apporter à UWP.

  2. Certaines caractéristiques/fonctionnalités du système de validation de WPF tirent parti des fonctionnalités de base de WPF qui n'existent pas dans UWP. Plus particulièrement, voici la couche d'ornement, qui permet à n'importe quel UIElement dans WPF d'afficher des visuels de validation, pas seulement des contrôles (via l'ajout d'une partie de modèle).

  3. UWP Xaml n'a pas actuellement le concept d'événements attachés, et la mise en miroir de la classe Validation ajouterait l'événement Validation.Error. Ce n'est pas une rupture d'accord, juste quelque chose à signaler car nous hésitons généralement à ajouter de nouveaux concepts, car cela ne fait qu'ajouter de la complexité. En plus de cela, étant donné que le travail nécessite des modifications du modèle de contrôle, seul l'ensemble de contrôles pour lequel nous fournissons les modifications de modèle spécifiques fonctionnerait immédiatement. De manière générale, avoir une API qui semble fonctionner, mais qui ne fonctionne pas dans certains scénarios n'est pas une bonne pratique, et nous pensions donc qu'il serait préférable de nous séparer de ce modèle. Cela signifierait avoir quelque chose d'autre comme une interface commune et/ou des attributs qui contrôlent l'implémentation.

Nous sommes toujours en train de comprendre comment effectuer des révisions d'API et de spécifications dans le nouveau monde passionnant de l'open source. Nous aimerions avoir les commentaires de la communauté, alors j'espère que nous pourrons bientôt publier les propositions d'API afin que la communauté puisse jeter un coup d'œil et nous aider à trouver quelque chose qui passionne tout le monde !

@stevenbrix Lorsque vous commencerez la spécification open source pour les fonctionnalités de validation, fournirez-vous les illustrations de l'apparence de la validation, ainsi que les exemples de scénarios afin que la conversation puisse être un peu plus large pour ceux d'entre nous qui sont plus du côté de l'interface utilisateur , que le codage :)

@mdtauk Absolument. L'interface utilisateur actuelle que nous avons partagée est toujours exacte. Si vous avez des commentaires, n'hésitez pas à donner sur ce fil.

@LucasHaines L'interface utilisateur me semble bonne. Mais je me demande comment vous pouvez ajuster la façon dont les erreurs sont affichées. Je n'ai rien trouvé à ce sujet et je ne sais pas si vous avez déjà quelque chose à partager dans ce domaine. Y aura-t-il quelque chose de similaire comme la propriété Validation.ErrorTemplate jointe de WPF ?

Existe-t-il un calendrier pour la publication d'une spécification/proposition formelle à cet effet ?
Que puis-je faire pour aider cela à entrer dans le produit plus tôt ?

Je suis d'accord avec @mrlacey ci-dessus... Je pourrais vraiment l'utiliser maintenant, donc je suis heureux d'aider là où je peux.

Nous travaillons sur une spécification ouverte et je ferai savoir à tout le monde qu'elle est disponible dans le référentiel de spécifications.

Question : pourquoi ne pas également prendre en charge IDataErrorInfo ? Il est pris en charge dans la norme .net, et ce serait bizarre de ne pas le prendre en charge ? Cela ne devrait pas affecter les performances pour les personnes qui ne l'utilisent pas car il pourrait même être vérifié au moment de la compilation quelle interface utiliser pour la liaison ?

Nous avons commencé l'examen des spécifications ouvertes pour la validation des entrées dans le référentiel des spécifications ouvertes. https://github.com/Microsoft/microsoft-ui-xaml-specs/pull/26

Salut les gars, comment suivons-nous cela - avons-nous un ETA ?

@knightmeister Nous avons une spécification ouverte créée ici . N'hésitez pas à participer à l'examen et à aider à façonner la fonctionnalité. Nous prévoyons de l'expédier dans le cadre de WinUI 3.0. Si vous souhaitez plus d'informations sur la feuille de route WinUI 3.0, consultez le numéro 717.

Salut tout le monde - veuillez jeter un coup d'œil aux derniers échantillons de la spécification. @stevenbrix a apporté d'excellentes mises à jour aux échantillons et a répondu à d'autres commentaires.

Une question : les informations de validation vont-elles passer dans la hiérarchie de contrôle ? Par exemple, sera-t-il possible pour un contrôle conteneur (par exemple TabView ou Pivot) de savoir qu'il existe un contrôle enfant dans un état invalide ?

Pensez à une vue complexe avec plusieurs contrôles de conteneurs, où vous souhaitez mettre en évidence les parties de la vue qui nécessitent votre attention, par exemple en modifiant le style d'un en-tête Pivot lorsqu'un contrôle enfant est dans un état non valide.

C'est une question cruciale pour moi.
L'ensemble de mon système de validation XAML est basé sur les règles de validation WPF, il lit le champ et le modèle d'entité à partir du BindingExpression et crée des règles de validation en fonction des attributs de validation DA (voir ceci ).

Par exemple, sera-t-il possible pour un contrôle conteneur (par exemple TabView ou Pivot) de savoir qu'il existe un contrôle enfant dans un état invalide ?

@tbolon oui, c'est quelque chose qui peut être fait, bien qu'il soit peu probable qu'il y ait un support intégré dans ces conteneurs pour cela. Nous avons pensé à créer un contrôle Form qui aurait cette fonctionnalité intégrée, mais c'est probablement en retard pour le moment. Comme dans WPF, il existe un événement ValidationError (ce nom peut être erroné) que chaque contrôle déclenche lorsqu'il devient invalide/valide. Cet événement n'est pas un événement routé, vous devez donc vous abonner à chaque élément que vous souhaitez écouter.

Tout mon système de validation XAML est basé sur les règles de validation WPF,

@weitzhandler, nous ne prévoyons pas actuellement d'ajouter quelque chose comme le ValidationRule à WinUI. Y a-t-il quelque chose que l'utilisation de this vous donne sur l'utilisation ValidationAttributes et que votre modèle implémente INotifyDataErrorInfo ? J'aimerais voir à quoi ressemblent votre modèle et XAML pour mieux comprendre votre scénario d'utilisation.

INDEI vous demande de mettre en place toutes vos entités et sous entités.
En utilisant des règles, aucune modification n'est requise, tout fonctionne automatiquement en utilisant uniquement les attributs de validation.

INDEI vous demande de mettre en place toutes vos entités et sous entités.

Pouvez-vous en dire plus ?

En utilisant des règles, aucune modification n'est requise, tout fonctionne automatiquement en utilisant uniquement les attributs de validation.

Pour la plupart, tout fonctionne automatiquement lorsque vous utilisez ValidationAttributes et INotifyDataErrorInfo également. Je vais montrer ici quelques extraits de code qui sont dans la spécification, juste pour que nous soyons (espérons-le) sur la même page.

FWIW, nous prévoyons d'avoir cette classe ValidationBase dans la boîte à outils, vous n'avez donc pas à écrire vous-même ce code passe-partout.

public class ValidationBase : INotifyPropertyChanged, INotifyDataErrorInfo
{
   public event PropertyChangedEventHandler PropertyChanged;
   public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

   protected void SetValue<T>(ref T currentValue, T newValue, [CallerMemberName] string propertyName = "")
   {
       if (!EqualityComparer<T>.Default.Equals(currentValue, newValue))
       {
           currentValue = newValue;
           OnPropertyChanged(propertyName, newValue);
       }
   }

   readonly Dictionary<string, List<ValidationResult>> _errors = new Dictionary<string, List<ValidationResult>>();
   public bool HasErrors
   {
       get
       {
           return _errors.Any();
       }
   }
   public IEnumerable GetErrors(string propertyName)
   {
       return _errors[propertyName];
   }

   private void OnPropertyChanged(string propertyName, object value)
   {
       PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
       Validate(propertyName, value);
   }

   private void AddErrors(string propertyName, IEnumerable<ValidationResult> results)
   {
       if (!_errors.TryGetValue(propertyName, out List<ValidationResult> errors))
       {
           errors = new List<ValidationResult>();
           _errors.Add(propertyName, errors);
       }

       errors.AddRange(results);
       ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
   }

   private void ClearErrors(string propertyName)
   {
       if (_errors.TryGetValue(propertyName, out List<ValidationResult> errors))
       {
           errors.Clear();
           ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
       }
   }

   public void Validate(string memberName, object value)
   {
       ClearErrors(memberName);
       List<ValidationResult> results = new List<ValidationResult>();
       bool result = Validator.TryValidateProperty(
            value,
            new ValidationContext(this, null, null)
            {
                MemberName = memberName
            },
            results
            );

        if (!result)
        {
            AddErrors(memberName, results);
        }
    }
}

Votre modèle dériverait alors de cette classe et ressemblerait à ceci :

public class Person : ValidationBase
{
    private string name;
    [MinLength(4)]
    [MaxLength(6)]
    public string Name
    {   
        get { return name; }
        set { SetValue(ref name, value); }
    }
}

En supposant que cette classe Person est définie sur une propriété ViewModel sur votre Page , vous vous liez ensuite à celle-ci et la validation se produit automatiquement :

<TextBox Text="{x:Bind ViewModel.Name, Mode=TwoWay}" />

Je comprends que cela puisse être un peu différent de ce que vous faites aujourd'hui, mais nous essayons de ne pas soutenir deux façons différentes de faire la même chose si nous n'en avons pas besoin. Faites-moi savoir si cela a du sens, ou si vous pensez qu'il nous manque encore quelque chose !

Vous avez raison, mais cela nécessite que vos entités ne soient pas des POCO.
Je devrais essayer. Ce n'est peut-être pas si mal d'utiliser une classe EntityBase dans une application LoB. J'ai juste l'habitude d'utiliser des POCO.

UWP n'a pas *HAVE Validation* !!!!!!! Je viens de lancer un projet. Retour à WPF jusqu'à quelques années.

@ rufw91 Je sais, n'est-ce pas ? !

Quelles sont vos contraintes de temps ? La première implémentation de ceci est dans l'alpha de WinUI3, et nous devrions avoir un aperçu du bureau WinUI à venir bientôt dans la période // Build. Nous prévoyons d'être en RTM d'ici la fin de l'année

UWP n'a pas *HAVE Validation* !!!!!!! Je viens de lancer un projet. Retour à WPF jusqu'à quelques années.

J'ai décidé de rester avec WPF pour les années à venir également. J'ai tout fait (WPF, SL, WP, UWP, etc), au final une seule technologie semble solide, c'est WPF. Peut-être que dans quelques années, il pourrait être intéressant de vérifier où en est WinUI, mais j'en ai assez de passer à de nouvelles technologies et d'être laissé seul dans le noir. WPF est mature et fonctionne très bien. Peut-être que dans quelques années, Windows en tant que système d'exploitation ne sera plus du tout pertinent, alors attendons cela avant d'investir davantage dans la plate-forme.

Peut-être que dans quelques années, Windows en tant que système d'exploitation ne sera plus du tout pertinent, alors attendons cela avant d'investir davantage dans la plate-forme.

Considérant que nous venons de dépasser le milliard d'installations de Windows 10, j'ai du mal à croire que ce sera un jour vrai. Mais je ressens définitivement votre frustration et ne vous reproche pas de rester sur WPF. FWIW, notre équipe s'approprie maintenant WPF, alors faites-moi savoir s'il y a quelque chose que vous voulez nous voir faire là-bas.

INDEI vous demande de mettre en place toutes vos entités et sous entités.

Pouvez-vous en dire plus ?

Avec mon code, toutes les entités POCO peuvent rester libres d'implémenter ces interfaces et rester sans classe de base. INPC est automatiquement mis en œuvre à l'aide de Fody. La plupart de ce que je ferais, c'est d'implémenter IValidatableObject lorsqu'une validation plus raffinée est requise. Et cela fonctionne également sur les sous-types.

FWIW, nous prévoyons d'avoir cette classe ValidationBase dans la boîte à outils, vous n'avez donc pas à écrire vous-même ce code passe-partout.

Ce n'est pas bon. Que se passe-t-il si mes entités ont déjà une classe de base ? C'est aussi pourquoi je ne suis pas un grand fan de INotifyDataErrorInfo . Les propriétés INPC sont déjà un casse-tête pour elles-mêmes, en particulier lorsqu'il s'agit d'applications de données massives avec des tonnes d'entités.

Il est assez choquant que UWP n'ait pas encore de validation appropriée. C'est une fonctionnalité de base cruciale dans presque toutes les applications et devrait être prioritaire.

Il est assez choquant que UWP n'ait pas encore de validation appropriée. C'est une fonctionnalité de base cruciale dans presque toutes les applications et devrait être prioritaire.

Oui, c'est pourquoi nous y travaillons :)

Ce n'est pas bon. Que se passe-t-il si mes entités ont déjà une classe de base ?

J'essaie juste de comprendre votre utilisation ici. Quelle est la classe de base, et pourrait-elle dériver de cette classe ?

Oui, c'est pourquoi nous y travaillons :)

Merci, très apprécié. Ceci, et le reste de votre travail.
Qu'implique l'étiquette needs-winui-3 ?

J'essaie juste de comprendre votre utilisation ici. Quelle est la classe de base, et pourrait-elle dériver de cette classe ?

J'utilise OData Connected Service pour obtenir des entités générées sur mon client.
Les objets générés sont de ce modèle :

c# public abstract partial class ContactBase : Microsoft.OData.Client.BaseEntityType, INotifyPropertyChanged

Qu'implique l'étiquette needs-winui-3 ?

@weitzhandler
Cela implique que la validation des entrées viendra avec WinUI 3. (3.0 comme actuellement prévu). Cela ne viendra probablement pas dans WinUI 2 car cela nécessiterait des modifications du code OS XAML qui est actuellement en mode maintenance.

J'utilise UWP dans une application Uno Platform. Espérons que WinUI sera couvert lors de sa sortie.
Merci pour la mise à jour !

J'essaie juste de comprendre votre utilisation ici. Quelle est la classe de base, et pourrait-elle dériver de cette classe ?

Avoir une classe de base est souvent mandaté par un tiers, par exemple le cadre de persistance que vous utilisez. UWP/WinUI exigeant également une classe de base uniquement pour la validation n'est pas une option. Il doit s'agir d'une interface pour être utile, aucune de nos applications ne pourrait utiliser une classe de base. (Cela ne signifie pas que vous ne pouvez pas avoir une classe de base pour les personnes qui souhaitent l'utiliser, cela doit juste être facultatif et pas la seule façon de faire la validation.)

Avoir une classe de base est souvent mandaté par un tiers, par exemple le cadre de persistance que vous utilisez. UWP/WinUI exigeant également une classe de base uniquement pour la validation n'est pas une option. Il doit s'agir d'une interface pour être utile, aucune de nos applications ne pourrait utiliser une classe de base.

Revenons un peu en arrière. Je pense que les derniers commentaires que j'ai faits ont causé un peu de confusion, ce qui est ma faute.

Tout ce dont le modèle aura besoin est d'implémenter System.ComponentModel.INotifyDataErrorInfo (ou Windows.UI.Xaml.Data.INotifyDataErrorInfo pour C++). Le compilateur générera correctement le code pour le connecter à votre vue lors de l'utilisation {x:Bind} .

La classe ValidationBase dont j'ai parlé ci-dessus est une classe d'assistance que nous avions l'intention d'inclure dans la boîte à outils de la communauté qui l'implémente, avec INotifyPropertyChanged . Il n'est pas nécessaire d'en dériver si votre cas d'utilisation ne le permet pas.

Merci pour vos précisions @stevenbrix.

Qu'en est-il des attributs de validation et IValidatableObject , vont-ils être respectés par le runtime UWP ?

Qu'en est-il des autres attributs, comme l'attribut MaxLength que vous avez mentionné précédemment, une longueur maximale TextBox sera-t-elle définie automatiquement comme dans ASP.NET ?
Idem avec DataTypeAttribute , EditableAttribute .
Également DisplayAttribute pour générer des en-têtes de champs.
Autant que je me souvienne, ils étaient tous pris en charge dans Silverlight.

(voir ceci ).

Qu'en est-il des attributs de validation et IValidatableObject, seront-ils respectés par le runtime UWP ?

Nous allons donc actuellement prendre en charge l'attribut Required . Certains contrôles mettront automatiquement un petit astérisque à côté du texte d'en-tête lorsqu'il est utilisé. Nous sommes ouverts à en soutenir davantage à l'avenir si vous le souhaitez. Veuillez ouvrir un problème séparé si vous souhaitez en savoir plus, et juste pour définir les attentes, il est très peu probable que toute prise en charge d'attribut supplémentaire fasse la version initiale de WinUI3.

Quant à IValidatableObject , je ne sais pas comment cela fonctionnerait. En général, notre moteur fonctionne simplement en écoutant l'événement INotifyDataErrorInfo.ErrorsChanged . La validation réelle du modèle appartient au développeur de l'application et est généralement effectuée lors du transfert de la valeur de la cible à la source.

Peut-être qu'en tant que méthode alternative au ValidationBase que vous avez proposé, il devrait y avoir un ensemble de méthodes d'extension, qui exécutent un processus de validation à l'aide Validator.TryValidateObject et injectent les résultats de la validation dans l'entité, notifiant les modifications ?
De cette façon, cela peut être réalisé facilement en implémentant simplement INotifyDataErrorInfo . Nous pourrions également avoir une interface qui hérite de INotifyDataErrorInfo qui ajoute une propriété qui contient la collection d'erreurs, de sorte que le runtime UWP ou la boîte à outils puisse reconnaître comme une entité validable automatisée à la place, et définir la propriété automatiquement si elle est implémentée.

Peut-être qu'en tant que méthode alternative à la ValidationBase que vous avez proposée, il devrait y avoir un ensemble de méthodes d'extension, qui exécutent un processus de validation à l'aide de Validator.TryValidateObject, et injectent les résultats de la validation dans l'entité, en notifiant les modifications ?

C'est une bonne idée :)

🦙 Vous vous demandez si les nouveaux paradigmes du générateur de sources pourraient également aider ici ?

Oui @michael-hawker, j'aime vos pensées !

J'ai eu les mêmes pensées il y a quelque temps lorsque j'ai lu pour la première fois les nouvelles possibilités du générateur de source.

Je pense qu'avec les nouveaux paradigmes de générateur de source, nous pouvons construire / générer beaucoup de choses dans les coulisses pour INotifyDataErrorInfo et INotifyPropertyChanged.

J'ai un cours WPF sur Pluralsight qui fait exactement cela avec T4, INotifyPropertyChanged et INotifyDataErrorInfo, y compris les annotations de données pour la validation : https://www.pluralsight.com/courses/wpf-mvvm-advanced-model-treatment
Le cours utilise également des propriétés jointes personnalisées pour connecter des éléments.
L'objectif de ce cours est de montrer comment vous pouvez créer une application MVVM WPF qui indique sur chaque champ d'entrée s'il a été modifié et quelle était la valeur d'origine.

Donc, certainement, générer des choses et peut-être se retrouver avec une bibliothèque (peut-être dans le cadre de WCT) serait génial. Et j'aimerais refaire ce cours pour WinUI. :)

@ rufw91 Je sais, n'est-ce pas ? !

Quelles sont vos contraintes de temps ? La première implémentation de ceci est dans l'alpha de WinUI3, et nous devrions avoir un aperçu du bureau WinUI à venir bientôt dans le délai // Build. Nous prévoyons d'être en RTM d'ici la fin de l'année

@stevenbrix J'espère que oui, j'ai dû revenir à WPF, je suis en fait presque fini maintenant.

J'ai ouvert celui- ci.

Pour faire suite à cela, après une conversation avec @stevenbrix sur Twitter, j'ai intégré l'implémentation de base INotifyDataErrorInfo qu'il a fournie ici dans une nouvelle classe ObservableValidator incluse dans le nouveau MVVM Toolkit (le bibliothèque Microsoft.Toolkit.Mvvm ), qui implémente également INotifyPropertyChanged et INotifyPropertyChanging 😄

Vous pouvez voir le code associé et un récapitulatif de tout ce qui concerne cette bibliothèque dans ce numéro .
J'y ai également inclus des liens vers le problème d'origine du MVVM Toolkit, ainsi que d'autres documents à ce sujet pour les nouveaux développeurs.

Pourriez-vous s'il vous plaît nous donner une mise à jour à ce sujet? Curieux de savoir si UWP 10.0 18362 prend en charge INotifyDataErrorInfo . Selon la page de documentation suivante, https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.inotifydataerrorinfo?view=netcore-3.1 INotifyDataErrorInfo "s'applique" à UWP 10.0. Cependant, avec UWP 10.0 18362 installé et ciblé, les zones de texte n'affichent pas les validations INotifyDataErrorInfo . Les zones de texte sont décrites en XAML comme suit :

<TextBox Text="{x:Bind ViewModel.Username, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

Et nous utilisons ReactiveValidationObject comme implémentation de INotifyDataErrorInfo ici.

@worldbeater ceci n'est disponible que dans les dernières prévisualisations de WinUI3, utilisez-vous cela ?

Merci @stevenbrix! Je vais essayer WinUI3. Heureux d'apprendre que INotifyDataErrorInfo et UWP se lient d'amitié, enfin ✨

@worldbeater , il est toujours en avant-première, nous aimerions donc avoir vos commentaires dessus ! 💪

@worldbeater au fait, la documentation indique qu'il est disponible sur UWP 10.0, mais cela ne signifie pas qu'il est pris en charge par celui-ci. La documentation n'est pas assez claire.

Cette page vous a été utile?
0 / 5 - 0 notes