Événement DatagridView

Messages postés
54
Date d'inscription
vendredi 23 mai 2008
Dernière intervention
21 septembre 2018
- - Dernière réponse : Whismeril
Messages postés
12390
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
14 décembre 2018
- 11 mars 2018 à 15:38
Bonjour,

Je possède un grid avec des colonnes qui contiennent des checkbox.
Je cherche l'événement qui me permettra d'effectuer une action lorsque la checkbox change d'état.
Ou alors je m'y prend mal pour effectuer ce que je veux y faire XD

Le context de mon dev est de charger dans un grid le nom des menus avec une autorisation ou non d'une visualisation et/ou d'une modification via une checkbox d'un utilisateur préalablement sélectionné.

Lorsqu'un utilisateur cliquera sur la checkbox de la colonne "visu" ou "modif" sur une ligne comprenant la valeur "&....." de la colonne "Menu" je veux que toutes les lignes qui suivent jusqu'au prochain "&......" se modifient en même temps.

voici mon grid
//Load FORMULAIRES
//Create Grid
m_grid.Rows.Clear();
m_grid.Columns.Clear();
m_grid.Columns.Add(Modules.General.CreateTextBoxColumn("Id", "Id"));
m_grid.Columns.Add(Modules.General.CreateTextBoxColumn("Menu", "Menu"));
m_grid.Columns.Add(Modules.General.CreateCheckBoxColumn("Visu", "Visu"));
m_grid.Columns.Add(Modules.General.CreateCheckBoxColumn("Modif", "Modif"));

m_grid.Columns["Id"].Visible = false;
m_grid.Columns["Menu"].ReadOnly = true;


Exemple de résultat depuis la BDD (1 pour True et 0 pour False) que le grid comprendra
Accueil 1 1
&Paramétrages 1 1
Dépôts 1 1
Services 1 1
Profils 1 1
RH 1 1
&RH 1 1
Liste RH BSG 1 1
Liste RH IDA 1 1

J'ai testé plusieurs événements avec le code suivant avec pour exemple l'événement cellValueChanged

private void m_grid_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
	if (e.ColumnIndex > 1)
	{
		bool NewValue = bool.Parse(m_grid[e.ColumnIndex, e.RowIndex].Value.ToString());

		string menu = m_grid["Menu", e.RowIndex].Value.ToString();
		if (menu.Substring(0, 1) == "&")
		{
			for (int i = e.RowIndex + 1; i < m_grid.RowCount; i++)
			{
				if (m_grid["Menu", i].Value.ToString().Substring(0, 1) != "&")
				{
					m_grid.Rows[i].Cells[e.ColumnIndex].Value = !NewValue;
				}
				else
				{
					m_grid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = !NewValue;
					break;
				}
			}
		}
	}
}


fonctionne que pour le premier clique. Si l'utilisateur ne change pas de cellule l'événement n'est plus valable :(

J'espère que j'ai au moins réussi à m'exprimer clairement o_O

Quelqu'un a une idée ?

Merci ;-)
--
Afficher la suite 

Votre réponse

7 réponses

Messages postés
54
Date d'inscription
vendredi 23 mai 2008
Dernière intervention
21 septembre 2018
0
Merci
En faite j'ai trouvé ma solution en rédigeant le post ^^

J'ai repris mon événement CellClick et j'ai ajouté avant mon break; :

m_grid.EndEdit();


Aussi simple que ça !

Si à la lecture mon mon code il y'a des incohérences ou des mal façon, je suis preneur car je débute en C# après de longue année en VB.net.

Merci à vous
--
Commenter la réponse de kyoku59
Messages postés
12390
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
14 décembre 2018
0
Merci
Bonjour
Si à la lecture mon mon code il y'a des incohérences ou des mal façon, je suis preneur car je débute en C# après de longue année en VB.net


C#, tout comme VB.Net sont des langages "tout" objet, optimisés pour le MVC.
Si tu codais comme ça en VB.Net, alors tu as passé de longues années à ne pas en profiter.
Le code que tu présentes c'est du VB6 transposé en C#.
Ça n'est pas une critique, juste un constat.
Le fait est que beaucoup de codeurs (notamment autodidactes) venant de VB6, n'arrivent pas à se faire au changement de philosophie que représente l'objet.

Dans ton cas, tu es obligé de tester de quelle colonne il s'agit, puis de faire un parse et ensuite tout un tas de trucs en fonction du contenu d'une autre colonne.
Et puis bien sûr pour ne pas attendre que la cellule change, tu doit gérer un endEdit dans l'évènement Click.

Si j'ai bien compris le but de ce code et ta hiérarchie de données

Accueil 1 1
&Paramétrages 1 1
Dépôts 1 1
Services 1 1
Profils 1 1
RH 1 1
&RH 1 1
Liste RH BSG 1 1
Liste RH IDA 1 1

& Paramétrages est le "père" de Dépôts 1, Services, Profils et RH.
Et quand je coche visu ou modif, ça décoche tous les enfants (ou inversement).

Ceci s'avère casse pied en winform avec un datagridview (qui n'est pas le contrôle le plus coopératif pour le binding), j'avais commencé un long message pour t'expliquer en détail, mais ça va t'embrouiller.

Donc je te propose la lecture de ce petit tuto
http://codes-sources.commentcamarche.net/faq/1291-utilisation-du-binding-au-travers-de-l-objet-databindingsource
Commenter la réponse de Whismeril
Messages postés
54
Date d'inscription
vendredi 23 mai 2008
Dernière intervention
21 septembre 2018
0
Merci
Merci Whismeril !

Je prend toutes les remarques constructive car je veux justement avancer et m'améliorer.
J'ai appris le VB.net en BTS et effectivement mes profs proche de la retraite sortaient tout droit du VB6... Et oui j'ai surement une logique a tendance VB6 :(.

Dans l'exemple je l'ai pas mis mais j'utilise du LINQ et impossible de m'afficher une checkbox dans mon grid du coup je créé a l'avance mes colonnes que je rempli avec ma reqête :

var listFormulaire = (from d in m_context.DROITS
					where d.Id_PROFILS == idProfil && d.Id != 1
					select d).OrderBy(p=> p.FORMULAIRES.Ordre).ToList();

foreach (var objDroit in listFormulaire)
{
	m_grid.Rows.Add(objDroit.Id, objDroit.FORMULAIRES.NomMenu, objDroit.Visu, objDroit.Modif);
}


--
Whismeril
Messages postés
12390
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
14 décembre 2018
-
Ben justement, le binding est bien plus adapté.
Lis le tuto, éventuellement teste le projet et on en reparle
kyoku59
Messages postés
54
Date d'inscription
vendredi 23 mai 2008
Dernière intervention
21 septembre 2018
-
En faite j'utilise le binding que mon context me propose mais les champs ne me convienne pas.
Si je comprend le tuto, je dois modifier ma classe en y ajoutant des instances avec ses accesseurs ? Le truc c'est que quand j'accède a ma classe "DROITS" par exemple, elle est vide du coup je me pose la question a savoir si je doit recréer une classe à ma sauce.

namespace Gestion_des_RF_4._0
{
    partial class DROITS
    {
    }
}

Ou alors je ne cherche pas au bon endroit.

En tout cas merci de ton aide !
Whismeril
Messages postés
12390
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
14 décembre 2018
-
Alors déjà cette classe est partielle, donc normalement, dans un autre fichier y'a la suite.

Sinon oui, créer une classe à ta sauce est une bonne solution.
kyoku59
Messages postés
54
Date d'inscription
vendredi 23 mai 2008
Dernière intervention
21 septembre 2018
-
Comment faire maintenant pour enregistrer mes modifications dans la BDD ?

Je charge un comboBox "Login".
Sur l'événement "SelectionChangeCommitted" je charge mes données avec mon nouveau Binding.

Ma nouvelle classe (assez basique pour commencer XD) et je test divers solutions :
    class Profil
    {
        /// <summary>
        /// initilaise des variables valables pour une instance
        /// </summary>
        #region Champs d'instances

        private PROFILS objProfil;
        private string login;
        private string mdp;
        #endregion

        #region Constructeurs d'instance
        public Profil(PROFILS objProfil)
        {
            this.objProfil = objProfil;

            this.login = objProfil.Login;
            this.mdp = objProfil.Mdp;
        }
        #endregion

        #region Propriétés
        public string Login
        {
            get { return login; }
            set { login = value; }
        }

        public string Mdp
        {
            get { return mdp; }
            set { mdp = value; }
        }

        public string Nom
        {
            get { return objProfil.RH.Nom; }
        }

        public string Prenom
        {
            get { return objProfil.RH.Prenom; }
        }
        #endregion


Puis dans ma form :
    public partial class FormTest : Form
    {
        private DataContext m_context;

        public FormTest()
        {
            InitializeComponent();
            m_context = new DataContext();
            pROFILSBindingSource.DataSource = m_context.PROFILS;
        }

        private void FormTest_Load(object sender, EventArgs e)
        {
            loginComboBox.SelectedValue = -1;
        }

        private void loginComboBox_SelectionChangeCommitted(object sender, EventArgs e)
        {
            var recup = m_context.PROFILS.Where(p => p.Id == int.Parse(loginComboBox.SelectedValue.ToString())).FirstOrDefault();

            Objets.Profil objProfil = new Objets.Profil(recup);
            profilBindingSource.DataSource = objProfil;
        }

        private void MAJ_Click(object sender, EventArgs e)
        {
            
        }
    }
Commenter la réponse de kyoku59
Messages postés
12390
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
14 décembre 2018
0
Merci
Le bindingsource dispose de la propriété Current qui contient l’instance « active ».
Du coup dans ton combobox pas besoin de recherche, et pour ta mise à jour il faut t’en servir aussi

        private void loginComboBox_SelectionChangeCommitted(object sender, EventArgs e)
        {
            PROFILS recup = (PROFILS)pROFILSBindingSource.Current;
            Objets.Profil objProfil = new Objets.Profil(recup);
            profilBindingSource.DataSource = objProfil;
        }

        private void MAJ_Click(object sender, EventArgs e)
        {
            profil AMettreAJour = (profil)profilBindingSource.Current;
            //code de maj à partir de l’instance
        }
    }


Quelques conseils:
  • evite les var quand tu connais le type
  • soit cohérent dans ta politique de nommage de classes, variables etc. Là tu as du tout majuscule, du camel case, du séparé par _

Commenter la réponse de Whismeril
Messages postés
54
Date d'inscription
vendredi 23 mai 2008
Dernière intervention
21 septembre 2018
0
Merci
Ha cool je commence a voir un peu le fonctionnement et comment le mettre à ma sauce.

Par contre quand je clique sur une ligne de mon comboBox il me charge ma ligne -1 et me modifie dans ma combo ma ligne sélectionné par le login a ligne -1. (pourtant je ne vois aucune relation entre ces 2 binding)

J'ai surement mal interprété une donnée :
1 : Je charge une comboBox avec avec un Binding de mon context
2 : sur sélection de la combo, je créé un Binding avec ma nouvelle classe qui comporte les informations souhaité

Pour ma nomenclature oui j'en suis conscient et j'aurai du modifier direct :)
"m_" pour mes variables de classe
Le tout majuscule (PROFILS) fait partie de mon context (nom de mes tables en majuscule)

Y'a-t-il une nomenclature sur l'appellation des objets visuel ? J'aurai tendance a dire que ce sont des variable de classe donc m_ + le nom d'objet (ex: m_login)

pour que ca soit plus claire :
       public partial class FormTest : Form
    {
        private DataContext m_context;

        public FormTest()
        {
            InitializeComponent();
            m_context = new DataContext();
            PROFILSBindingSource.DataSource = m_context.PROFILS.Select(p=> p).ToList();
        }

        private void FormTest_Load(object sender, EventArgs e)
        {
            loginComboBox.SelectedValue = -1;
        }

        private void loginComboBox_SelectionChangeCommitted(object sender, EventArgs e)
        {
            m_context.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues);

            objProfilBindingSource.ResumeBinding();
            PROFILS recup = (PROFILS)PROFILSBindingSource.Current;
            Objets.Profil objProfil = new Objets.Profil(recup);
            objProfilBindingSource.DataSource = objProfil;
        }

        private void MAJ_Click(object sender, EventArgs e)
        {
            PROFILS updateProfil = (PROFILS)PROFILSBindingSource.Current;
            updateProfil.Login = loginTextBox.Text;
            updateProfil.Mdp = mdpTextBox.Text;

            m_context.SubmitChanges();
        }
    }


Et lorsque je mets à jour mon context, le prend en mémoire toute les modif faite. Du coup je cherche a réactualiser chacune des données si la sélection du profil change.

Ca fait beaucoup de question tout ça ^^

En tout cas tu m'as permis de me lancer dans le binding

--
Commenter la réponse de kyoku59
Messages postés
12390
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
14 décembre 2018
0
Merci
Y'a-t-il une nomenclature sur l'appellation des objets visuel ?


Il y a des recommandations, pour ce qui est public CamelCase et pour ce qui est privé camelCase.
Mais rien n'est obligé, l'important est d'avoir une cohérence.

Par contre,
private DataContext m_context;
c'est pas une variable de classe, c'est une variable d'instance.
Une variable de classe n'a pas besoin d'un new pour exister, par exemple
Math.Pi
, elle est déclarée avec le modificateur static.

Là je ne comprends pas
Par contre quand je clique sur une ligne de mon comboBox il me charge ma ligne -1 et me modifie dans ma combo ma ligne sélectionné par le login a ligne -1. (pourtant je ne vois aucune relation entre ces 2 binding)

kyoku59
Messages postés
54
Date d'inscription
vendredi 23 mai 2008
Dernière intervention
21 septembre 2018
-
merci pour le détail.

Pour remettre dans le context :
J'ai une combo ui est chargé avec un binding "PROFILSBindingSource"
Lorsque je sélectionne un item, le binding "objProfilBindingSource" rempli certain textbox.

lorsque je sélectionne un item dans ma combo, celle-ci est modifié.
- Si 1er item, tous les champs se remplissent correctement et ma combo reste inchangé.
- Si autre, la combo charge systématiquement le 1er item dela combo et l'affichage du 1er item devient celui sélectionné.

Exemple de données :
login----------Mdp-----------Nom---------Prenom
vincentB----%vincent---B---------------Vincent
julienL------- %julien------L---------------Julien
jhonnyM-----%jhonny---M-------------Jhonny

Exemple sur sélection du 1er item :
combo :
=> vincentB
- JulienL
- JhonnyM

Texbox :
Login : vincentB
mdp : %vincent
Nom : B.
Prénom : Vincent

combo :
- vincentB
- JulienL
- JhonnyM
------

Sélection du dernier item
combo :
- vincentB
- JulienL
=> JhonnyM

charge
Login : vincentB
mdp : %vincent
Nom : B.
Prénom Vincent

combo :
- JhonnyM
- JulienL
- JMJhonnyM
----

Dans la foulé sélection du deuxième item :
combo :
- JhonnyM
=> JulienL
- JhonnyM

charge
Login : JhonnyM
mdp : %julien
Nom : R.
Prénom Jhonny

combo :
- JhonnyM
- JulienL
- JulienL

Je pense avoir réussi a expliquer le phénomène XD
Commenter la réponse de Whismeril
Messages postés
12390
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
14 décembre 2018
0
Merci
Ok, faudra que j’essaye, et je n’ai pas trop de temps en ce moment.
Par contre, en winform c’est quand même assez limité.

Si tu es motivé, je te conseille de passer au wpf, c’esr 100 plus puissant, et avec un peu de maîtrise tu peux faire des design super léchés
kyoku59
Messages postés
54
Date d'inscription
vendredi 23 mai 2008
Dernière intervention
21 septembre 2018
-
Oui j'aimerai bine me mettre au WPF. As-tu une recommandation ?

C'est mieux de faire une appli 100% WPF ou peut-on mélanger avec du Winform ?
Whismeril
Messages postés
12390
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
14 décembre 2018
-
Tu peux integrer des controles winform, mais franchement aucun intérêt.
Pour le cours, le livre WPF par la pratique de Thomas Lebrun est très bien (c’est pas moi, et je n’ai pas de royalties).
Le temps que tu suives le cours, laisse ton projet de coté, fais les exercices.
Ensuite tu pourras voir si tu passes ton projet en wpf et éventuellement poser des questions ici.
kyoku59
Messages postés
54
Date d'inscription
vendredi 23 mai 2008
Dernière intervention
21 septembre 2018
-
Bouquin acqui !

Merci en tout cas pour tes explications. Malgré le fait de ne pas avoir réussi a faire ce que je voulais (pour l'instant) tu m'as mis sur la voie du binding et du wpf !

Ne me reste plus qu'a le lire et le comprendre.
Whismeril
Messages postés
12390
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
14 décembre 2018
-
de rien
Commenter la réponse de Whismeril

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.