Récupérer le contenu d'un datagridview [Résolu]

chambreur 30 Messages postés mardi 19 août 2008Date d'inscription 15 mai 2014 Dernière intervention - 21 janv. 2014 à 14:40 - Dernière réponse : yann_lo_san 1137 Messages postés lundi 17 novembre 2003Date d'inscription 23 janvier 2016 Dernière intervention
- 23 janv. 2014 à 13:22
Bonjour,
Je possède un datagridview généré à partir d'une datatable créée a partir de 3 lists.
Je souhaites désormais récupérer le contenu des lignes modifiées par l'utilisateur par l'intermédiaire du datagridview, mettre les nouvelles lignes dans une autre liste et les comparer.
on sait que le code suivant fonctionne et permet de récupérer la valeur d'une seul cellule:
string case1 = datagridview1[1, 0].Value.ToString();

Je souhaite donc récupérer toute une ligne et l'insérer dans une liste comme ceci
List<string> NelleListe = new List<string>();
NelleListe = datagridview1.Rows[2].Cells.ToList(); 

Ceci bien évidement ne fonctionne pas. Peut être qu'il n'y a pas de solution simple et que je dois ajouter les cellules une à une dans une liste mais je pense qu'il doit y avoir une solution pour faire ça en 1 coup (très rapidement)

tout comme
List<string> times = temps.OfType<string>().ToList();
dt.Rows.Add(times.ToArray());  // sert à  afficher les lignes du tableau

M'a permis de créer très facilement ma datatable

Une idée?
Afficher la suite 

7 réponses

Répondre au sujet
Whismeril 11428 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 24 avril 2018 Dernière intervention - 22 janv. 2014 à 20:15
+4
Utile
Bonsoir, c'est pour ça que je t'avais orienté vers le binding lors de ta présente question.

soit le fichier xml suivant
<?xml version="1.0" encoding="utf-8" ?> 
- <ListeDeContacts>
- <Contact>
  <Nom>Di</Nom> 
  <Prenom>Alain</Prenom> 
  <Naissance>01/02/1900</Naissance> 
  </Contact>
- <Contact>
  <Nom>Sor</Nom> 
  <Prenom>Jean</Prenom> 
  <Naissance>01/01/1900</Naissance> 
  </Contact>
- <Contact>
  <Nom>Zétofrai</Nom> 
  <Prenom>Mélanie</Prenom> 
  <Naissance>01/03/1900</Naissance> 
  </Contact>
  </ListeDeContacts>



tu veux lire et afficher ce fichier dans un datagridview et que les modifications de l'utilisateur soient enregistrées

I j'écris une classe qui décrit ma structure de données
using System;

namespace test
{
    public class Contact
    {
        public string Nom { get; set; }

        public string Prenom { get; set; }

        public DateTime Naissance { get; set; }
    }
}

c'est réduit au strict minimum, 1 using 3 propriétés

II j'écris une classe statif qui lit et écrit le xml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace test
{
    public static class AccesXML
    {

        /// <summary>
        /// Méthode pour lire le xml
        /// </summary>
        /// <param name="fichier">chemin du fichier</param>
        /// <returns>une liste de contacts</returns>
        public static List<Contact> LireContacts(string fichier)
        {
            XDocument xDoc = XDocument.Load(fichier);

            List<Contact> contacts;// on peux éviter cette ligne mais je décompose pour l'exemple

            contacts = (from c in xDoc.Descendants("Contact")//dans xDoc, on passe en revue chaque occurence de "Contact"
                        select new Contact//crée une nouvelle instance de ma classe Contact
                        {
                            Nom = c.Element("Nom").Value,
                            Prenom = c.Element("Prenom").Value,
                            Naissance = Convert.ToDateTime(c.Element("Naissance").Value)
                        }
                        ).ToList<Contact>();//cast le resultat de la requette du type Iennumerable<Contact> en List<Contact>

            return contacts;
        }

        /// <summary>
        /// Méthode qui ecrit le xml
        /// </summary>
        /// <param name="Contacts">La liste de contacts</param>
        /// <param name="fichier">chemin du fichier</param>
        public static void EcritContacts(List<Contact> Contacts, string fichier)
        {
            XDocument xDoc = new XDocument(
                                new XElement("ListeDeContacts", //une balise 
                                        from c in Contacts
                                        orderby c.Prenom ascending //triés par prénom pour le principe 
                                        select new XElement("Contact",
                                        new XElement("Nom", c.Nom),//on écrit l'élement Nom
                                        new XElement("Prenom", c.Prenom),//on écrit l'élement Prénom
                                        new XElement("Naissance", c.Naissance.ToShortDateString())// on écrit l'élément date de naissance 
                                )));
            xDoc.Save(fichier);
        }
    }
}

L'intérêt de faire une classe static à voir dans les commentaires du formulaire


III Je prends, un formulaire tout neuf, j'y mets un datagridview et le binde sur ma classe Contact par cette méthode
Dans le load j'appelle la méthode qui remplie le tableau et dans l'événement contactBindingSource_CurrentItemChanged la méthode qui sauve le xml.

using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;

namespace test
{
    public partial class Form4 : Form
    {

        List<Contact> contacts;

        public Form4()
        {
            InitializeComponent();
        }

        private void Form4_Load(object sender, EventArgs e)
        {
            AfficheContact();
        }

        /// <summary>
        /// affiche le fichier xml dans le datagridview
        /// </summary>
        private void AfficheContact()
        {
            if (File.Exists("Contacts.xml"))
                contacts = AccesXML.LireContacts("Contacts.xml");//charge le fichier s'il existe
                //on voit ici l'interet que AccesSML soit une classe statique:
                //il n'y a pas besoin d'instancier une variable pour utiliser la méthode
            else
                contacts = new List<Contact>();//sinon initialise une liste vide

            contactBindingSource.DataSource = contacts;//binde la liste de contacts
        }

        /// <summary>
        /// enregistre le xml dès qu'une entrée est validée dans le datagridview
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void contactBindingSource_CurrentItemChanged(object sender, EventArgs e)
        {
            if (contacts.Count > 0)
                AccesXML.EcritContacts(contacts, "Contacts.xml");
                //on voit ici l'interet que AccesSML soit une classe statique:
                //il n'y a pas besoin d'instancier une variable pour utiliser la méthode
            else
                File.Delete("Contacts.xml");
        }
    }
}


et voilà (clique sur l'image pour agrandir)



Dans cet exemple au moindre changement validé dans le datagridview (on quitte une cellule ou on tape sur entrée), le xml est modifié.
Ce qui implique qu'en cours de création d'un nouveau contact le xml présente un enregistrement moitié rempli, mais j'ai codé vite fait.
On peut aussi ajouter un bouton "Enregistrer" et ne pas se servir de l'événement.

PS pour les jeux de mots j'ai changé l'ordre des colonnes ;-)
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de Whismeril
romagny13 710 Messages postés lundi 10 janvier 2005Date d'inscription 27 août 2014 Dernière intervention - 21 janv. 2014 à 14:45
Commenter la réponse de romagny13
chambreur 30 Messages postés mardi 19 août 2008Date d'inscription 15 mai 2014 Dernière intervention - 21 janv. 2014 à 15:15
0
Utile
Merci pour ta réponse mais c'est un peu compliqué à mettre en oeuvre vu mon niveau. Peux tu détailler un peu plus stp. Voilà ce que j'ai écrit:
List<string> NelleListe = new List<string>();
foreach (DataGridViewRow row in datagridview1.SelectedRows)
 {
      NelleListe = row.DataBoundItem as List<string>;
  }

Je pense pas que ça soit la bonne solution car je souhaite pouvoir récupérer mes 3 listes ce qui n'est pas le cas si j'utilise le foreach(qui mettra toutes les lignes dans une seule liste).
Sinon, c'est peut être une meilleure idée de passer dans un premier temps par une datatable?
Commenter la réponse de chambreur
Whismeril 11428 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 24 avril 2018 Dernière intervention - 21 janv. 2014 à 19:07
0
Utile
Bonsoir,

alors si je comprends bien, au départ tu as 3 listes, tu moulines ça pour en faire une datable, que tu affiches dans un datagridview.
Tu veux ensuite récupérer les nouvelles entrées de l'utilisateur dans une 4eme liste.

Ça fait beaucoup de conteneurs de données non?
Tu pourrais directement injecter le moulinage (via Linq) dans une liste qui serait bindée à ton datagridview (je t'ai donné un lien là dessus la dernière fois)
A chaque changement dans le datagridview la liste bindée sera mise à jour et tu compares au moulinage.

Si tu postes les structure de tes listes (si c'est des classes perso la liste des propriétés, sinon le type des données), et ce que tu veux afficher et comparer avec le datagridview je veux bien t'aider à trouver la requête Linq qui va bien.
Commenter la réponse de Whismeril
chambreur 30 Messages postés mardi 19 août 2008Date d'inscription 15 mai 2014 Dernière intervention - Modifié par chambreur le 22/01/2014 à 14:16
0
Utile
Merci Whismeril mais c'est encore plus compliqué que cela!
Au départ j'ai un fichier Xml avec plein de données. Je récupère que 3 éléments que je vais afficher sous forme de listes.
Comme je veux afficher ces éléments sous forme d'un tableau, je créé un datagridview via un datatable dans lequel j'ai mis mes listes en tant que lignes.
Ensuite je vais récupérer le datagridview modifié puis reconstruire mes listes et enfin écraser le Xml avec les nouvelles données.

J'ai trouvé pour convertir le datagridview en datatable:
DataTable dt = dataGridView1.DataSource as DataTable;

Maintenant j'essaie de reconstruire mes listes mais la méthode que j'utilise est sans doute fastidieuse, voici un exemple pour une seule liste:
int colonne = dt.Columns.Count;
string VariableInter = "";
string[] exemple1 = new string[colonne -1];
for (int i = 0; i < colonne -1 ; i++)
 {
      VariableInter = dt.Rows[0]["t" + i].ToString();
      exemple1[i] = VariableInter;
  }
 List<string> Liste1 = new List<string>(exemple1);


Je cherche donc à améliorer cette dernière, car c'est pas terrible de repasser par un tableau pour récupérer une ligne que je souhaite mettre dans une liste.
Une idée?
Commenter la réponse de chambreur
chambreur 30 Messages postés mardi 19 août 2008Date d'inscription 15 mai 2014 Dernière intervention - Modifié par chambreur le 22/01/2014 à 15:02
0
Utile
Je viens de réussir sans passer par le tableau, voici mon code:
DataTable dt = dataGridView1.DataSource as DataTable;

List<string> ligne1 = new List<string>();

 foreach (DataColumn col in dt.Columns)
 {
    ligne1.Add(dt.Rows[0][col].ToString());
 }
Commenter la réponse de chambreur
yann_lo_san 1137 Messages postés lundi 17 novembre 2003Date d'inscription 23 janvier 2016 Dernière intervention - 23 janv. 2014 à 13:22
0
Utile
Salut,

les lignes d'un DataTable sont des objets DataRow.
DataRow expose ItemArray qui est un tableau d'object.

Donc, on peut extraire une ligne de plusieurs champs dans une String (séparé par des tabulations par exemple ou autre)

// un DataTable valide
DataTable unDataTable;

// une variable pour la ligne 1, une action pour la concaténation
static string _sLigne1 = "";
private static void ConcatArrValues(object val)
{
    // on peut faire un switch su le TYPE des obj et les formater
    _sLigne1 += val.ToString(/*fmt ici*/) + ((char)0x09);
}

// Extrait la ligne complète du DataRow 0 de la DataTable
Action<object> action = new Action<object>(ConcatArrValues);
Array.ForEach(unDataTable.Rows[0].ItemArray, action);


// _sLigne1 est remplie

Bye...
Commenter la réponse de yann_lo_san

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.