Menu

Valider la modification d'une cellule Datagrid WPF [Résolu/Fermé]

Messages postés
85
Date d'inscription
dimanche 11 janvier 2009
Statut
Membre
Dernière intervention
19 décembre 2018
- - Dernière réponse : Whismeril
Messages postés
13412
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
17 juin 2019
- 15 juin 2018 à 21:13
Bonjour à tous,

Donc, je vous explique mon petit problème!

Je suis entrain de faire une petite application en WPF! J'aimerai pouvoir modifier certaines cellules mais je veux pouvoir vérifier la nouvelle valeur! (Par exemple je veux pas qu'elle soit vide! )J'ai vu pas mal de documentation sur l'event "DataGridViewCellValidatingEventArgs" mais il me semble que c'est sur un Winform, du coup, j'ai l'impression que je ne peux déclencher cet event...

Est ce que quelqu'un aurait une idée?

Merci d'avance!





Afficher la suite 

3 réponses

Messages postés
85
Date d'inscription
dimanche 11 janvier 2009
Statut
Membre
Dernière intervention
19 décembre 2018
3
0
Merci
C'est bon j'ai réussi à contourner le problème! En créant une petite méthode dans la classe qui est en Binding pour vérifier que il y a bien quelque chose d'encodé!.

Voici un gros résumé du code:

<DataGrid x:Name="UsersGrid" HorizontalAlignment="Left" Height="185" VerticalAlignment="Top" 
         Width="766" IsSynchronizedWithCurrentItem="False" AutoGenerateColumns="False"  
          ColumnWidth="*" CanUserAddRows="False" PreviewKeyDown="UsersGrid_PreviewKeyDown"
          BeginningEdit="UsersGrid_BeginningEdit" CellEditEnding="UsersGrid_CellEditEnding">
                        <DataGrid.Columns>
                            <DataGridTextColumn Header="Nom" Width="*" Binding="{Binding Path=Nom,UpdateSourceTrigger=LostFocus}" />
                            <DataGridTextColumn Header="Prenom" Width="*" Binding="{Binding Path=Prenom,UpdateSourceTrigger=LostFocus}" />
                            <DataGridTextColumn Header="Profil" Width="*" Binding="{Binding Path=Profil}" IsReadOnly="True"/>
                            <DataGridTextColumn Header="Password" Width="*" Binding="{Binding Path=Password,UpdateSourceTrigger=LostFocus}" />
                        </DataGrid.Columns>
 </DataGrid>


 public  class Class
{
        #region VariablesMembres
        protected string _nom;
        #endregion

        #region Constructeurs

        public User(string nom, string prenom, string password)
        {
            _nom = nom;
            _prenom = prenom;
            _password = password;
        }
        #endregion

        #region Propriétés
        public string Nom
        {
            get { return _nom; }
            set
            {
                _nom = CheckEmpty(_nom,value);
            }
        }



        private string CheckEmpty(string oldValue, string newValue)
        {
            if (newValue.Length == 0)
                return oldValue;
            return newValue;

        }
}

Messages postés
13412
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
17 juin 2019
346
0
Merci
Bonsoir,

Il est fortement recommandé d’implémenter INotifyPropertyChanged dans les classes bindées.
En l’état si une propriété est modifiée par ailleurs (accès base de données, calcul, flux réseau etc...) le changement ne sera pas affiché. Alors qu’avec INotifyPropertyChanged

Pour la validation de données, ta méthode est une solution possible.
En voici une autre https://docs.microsoft.com/fr-fr/dotnet/framework/wpf/data/how-to-implement-binding-validation
aure2015
Messages postés
85
Date d'inscription
dimanche 11 janvier 2009
Statut
Membre
Dernière intervention
19 décembre 2018
3 -
Bonsoir!

Mon INotifyPropretyChanged est bien implémenté! Je l'avais juste pas recopié!

Par contre en ce qui concerne la validation,des données, 'ai un autre problème.
Mes données sont dans une BindingList<User> et j'aimerais ne pas avoir un nom et un prénom identique.
Pour l'ajout pas de soucis, j'ai une petite fonction qui parcourt la liste et qui compare les users avec la fct equal (redéfinie) et qui ajoute si il y en a d'identiques.

Par contre, pour la modification ça pose problème, je n'ai pas l'impression que la deuxième méthode que vous me proposez me permet de parcourir ma liste. Auriez-vous une idée?
Messages postés
13412
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
17 juin 2019
346
0
Merci
Alors la validation de données ne concerne que le format, dans l'exemple, cela bloque l'entrée à un entier de 21 à 130.
Dans ton cas, le code serait plus simple, puisque tu as dis vouloir juste vérifier que les champs ne sont pas vide (à savoir qu'une seul règle est à définir pour tes 3 propriétés).

Pour ton second besoin de vérification de doublon, il faudrait pouvoir passer en paramètre ta liste, l'objet en cours et chercher si la future valeur n'est pas un futur doublon. Cela dépasse le cadre "Est ce que ce texte a le format voulu" et n'est pas réutilisable.

Je te conseille de faire une vérification à postériori, et plutôt qu'une ibindingList, utiliser une ObservableCollection

using System.ComponentModel;

namespace Test_WPF
{
    public class User : INotifyPropertyChanged
    {
        private string nom;
        /// <summary>
        /// Nom de l'utilisateur
        /// </summary>
        public string Nom
        {
            get { return nom; }
            set
            {
                if (nom != value)
                {
                    nom = value;
                    GenerePropertyChanged("Nom");
                }
            }
        }

        private string prenom;
        /// <summary>
        /// Prénom de l'utilisateur
        /// </summary>
        public string Prenom
        {
            get { return prenom; }
            set
            {
                if (prenom != value)
                {
                    prenom = value;
                    GenerePropertyChanged("Prenom");
                }
            }
        }

        private string password;
        /// <summary>
        /// Mot de passe
        /// </summary>
        public string Password
        {
            get { return password; }
            set
            {
                if (password != value)
                {
                    password = value;
                    GenerePropertyChanged("Password");
                }
            }
        }

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        private void GenerePropertyChanged(string Propriete)
        {
            if (this.PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(Propriete));
        }

        #endregion


    
    }
}


        ObservableCollection<User> users;
        public MainWindow()
        {
            InitializeComponent();


            users = new ObservableCollection<User>
            {
                new User{Nom= "Sors", Prenom = "Jean", Password = "1234"},
                new User{Nom= "Zetofrais", Prenom = "Mélanie", Password = "1234"},
                new User{Nom= "Di", Prenom = "Alain", Password = "1234"},
            };


            users.CollectionChanged += Users_CollectionChanged;

            users.Add(new User { Nom = "Menvu", Prenom = "Gérard", Password = "1234" });

            users[2] = new User { Nom = "Sors", Prenom = "Jean", Password = "1234" };

//etc...


        private void Users_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
           switch (e.Action)
            {

                case NotifyCollectionChangedAction.Add:
                case NotifyCollectionChangedAction.Replace:
                    User encours = e.NewItems[0] as User;

                    if (users.Except(new[] { encours }).Any(u => u.Nom == encours.Nom && u.Prenom == encours.Prenom))
                        throw new Exception("L'utilistateur existe déjà");

                    break;
            }
        }


Par contre ça ne marche pas avec la modification d'une propriété, il faut s'abonner au PropertyChanged chaque objet.

Pour cela on reprend le code ainsi (par exemple)

        ObservableCollection<User> users = new ObservableCollection<User>();
        public MainWindow()
        {
            InitializeComponent();

            users.CollectionChanged += Users_CollectionChanged;

            users.Add(new User { Nom = "Sors", Prenom = "Jean", Password = "1234" });
            users.Add(new User { Nom = "Zetofrais", Prenom = "Mélanie", Password = "1234" });
            users.Add(new User { Nom = "Di", Prenom = "Alain", Password = "1234" });
            users.Add(new User { Nom = "Menvu", Prenom = "Gérard", Password = "1234" });

            //users[2] = new User { Nom = "Sors", Prenom = "Jean", Password = "1234" };

            users[3].Nom = "Sors";
            users[3].Prenom = "Jean";


        private void Users_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {

                case NotifyCollectionChangedAction.Add:
                case NotifyCollectionChangedAction.Replace:
                    User encours = e.NewItems[0] as User;

                    encours.PropertyChanged += Encours_PropertyChanged;

                    if (IsDoublon(encours))
                        throw new Exception("L'utilistateur existe déjà");

                    break;
            }
        }

        private bool IsDoublon(User EnCours)
        {
            return users.Except(new[] { EnCours }).Any(u => u.Nom == EnCours.Nom && u.Prenom == EnCours.Prenom);
        }

        private void Encours_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "Nom":
                case "Prenom":
                    if (IsDoublon((User)sender))
                        throw new Exception("L'utilistateur existe déjà");

                    break;
            }
        }


Quand j'étais petit, la mer Morte n'était que malade.
George Burns