Afficher dans un DataGridView à partir d'une classe

Signaler
-
Messages postés
14463
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
4 juillet 2020
-
Bonjour, je me permet de poser ma question car j'ai une classe qui me permet de récupérer des valeurs à partir d'un fichier texte, j'aimerai pouvoir les renvoyer sur ma form d'origine qui elle contient mon DataGrid et pouvoir justement les afficher dans le DataGrid, j'aimerais aussi savoir si le DataGrid me permettais d'afficher une grande quantité de valeurs.
Merci à vous ^^



Configuration: Windows / Chrome 80.0.3987.149

38 réponses

Messages postés
14463
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
4 juillet 2020
553
Bonjour

Attention un Datagrid et un Datagridview sont 2 contrôles différents.

Commence par là
https://codes-sources.commentcamarche.net/faq/1291-utilisation-du-binding-au-travers-de-l-objet-databindingsource
C'est bien un DataGridView je vais suivre le tuto je me tournerais vers toi si cela ne fonctionne pas, Merci !
J'ai pas trouver la réponse à ma question mon datagridview est bien bind à ma classe je retourne bien les valeurs après avoir trier mais je sais pas si je les affiches correctement
string result;
foreach (string chemin in cheminFichierOk)
i++;
for (int j = 0; j < i; j++)
{
IEnumerable<string> lines = File.ReadLines(cheminFichierOk[j]);
result = Path.GetFileName(cheminFichierOk[j]);
foreach (var item in lines)
{
LogParse leLog = LogParse.Parse(item, result);
lesLogs.Add(leLog);
}
}

je pense que mon soucis vien d'ici, comment je peux afficher à partir d'une list ?
Messages postés
14463
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
4 juillet 2020
553
Tu as essayé d'utiliser les balises de codes, afin de le faire correctement pour la suite, voici un court tuto https://codes-sources.commentcamarche.net/faq/11288-les-balises-de-code

Pour ton problème, si ça ne s'affiche, ça n'est pas bindé comme il faut.
Ça doit ressembler à un truc comme ça
monDataGridview.Datasource = monInstanceDeClasse.lesLogs;

si tu bindes sans bindingSource

ou
lesLogsBindingSource.Datasource = monInstanceDeClasse.lesLogs;
Aucune des deux méthodes fonctionne je dois mal m'y prendre mais mon DataGridView est bind à ma classe qui me permet de trier et quand j'ai finis le trie je lui retourne les valeurs en fonction des colonnes

return new LogParse
                    {
                        Datation = date,
                        Identificateur = "Nom",
                        Module = ligneArray[1],
                        Type = ligneArray[2],
                        Info = ligneArray[3],
                        Details = ligneArray[4],
                    };
Messages postés
14463
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
4 juillet 2020
553
Bonjour,

ce code est-il dans le même formulaire que le datagridview?
string result;
foreach (string chemin in cheminFichierOk)
i++;
for (int j = 0; j < i; j++)
{
  IEnumerable<string> lines = File.ReadLines(cheminFichierOk[j]);
  result = Path.GetFileName(cheminFichierOk[j]);
  foreach (var item in lines)
  {
    LogParse leLog = LogParse.Parse(item, result);
    lesLogs.Add(leLog);
  }
}

Et après l’exécution de ce code, y a t il truc du genre
MonDatagridview.DataSource = lesLogs;

Ou
LogParseBindingSource.DataSource = lesLogs;

?
Oui je passe par la première option,
dtgLog.DataSource = lesLogs;

je sais pas si c'est important mais je passe par un BackGroundWorker
Messages postés
14463
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
4 juillet 2020
553
Ha oui, y'a des chances.
Je ne sais pas quelle est le type de ta collection LesLogs, dans un premier temps essaye de mettre ObservableCollection<LogParse> (t'auras peut être un using à ajouter).

Si ne marche pas, il faudra que tu montres plus de code
C'est une list, le Observable n'a rien donner du coup voici ma form,
namespace AnalyseTool
{
    public partial class AnalyseForm : Form
    {
        public string dateDebut;
        public string dateFin;
        private string lcPath = ConfigurationManager.AppSettings["LogisticCorePath"];
        private string TraficPath = ConfigurationManager.AppSettings["TraficPath"];

        public AnalyseForm()
        {
            InitializeComponent();
        }

        private void AnalyseForm_Load(object sender, EventArgs e)
        {
        }

        private List<LogParse> lesLogs = new List<LogParse>();

        public void ChargerFichier(int i, List<string> cheminFichierOk)
        {
            string result;
            foreach (string chemin in cheminFichierOk)
                i++;
            for (int j = 0; j < i; j++)
            {
                IEnumerable<string> lines = File.ReadLines(cheminFichierOk[j]);
                result = Path.GetFileName(cheminFichierOk[j]);
                foreach (var item in lines)
                {
                    LogParse leLog = LogParse.Parse(item, result);
                    lesLogs.Add(leLog);
                }
            }
            lesLogs = lesLogs.OrderBy(x => x.Datation).ToList();
            dtgLog.DataSource = lesLogs;
        }

        public void dtpDebut_ValueChanged(object sender, EventArgs e)
        {
        }

        private void btnType_Click(object sender, EventArgs e)
        {
            Type type = new Type();
            type.ShowDialog();
        }

        private void btnExport_Click(object sender, EventArgs e)
        {
            Export export = new Export();
            export.ShowDialog();
        }

        private void btnPlay_Click(object sender, EventArgs e)
        {
            if (!backgroundWorker1.IsBusy)
            {
                backgroundWorker1.RunWorkerAsync();
            }
        }

        private void dtpFin_ValueChanged_1(object sender, EventArgs e)
        {
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            DateTime dateDebut = this.dtpDebut.Value, dateFin = this.dtpFin.Value;
            int i = 0;
            List<string> cheminFichier;
            AnalyseLog analyseLog = new AnalyseLog();
            cheminFichier = analyseLog.IntervaleFichierGlobal(lcPath, dateDebut, dateFin);
            analyseLog.ChargerFichier(i, cheminFichier);
            cheminFichier = analyseLog.IntervaleFichierGlobal(TraficPath, dateDebut, dateFin);
            analyseLog.ChargerFichier(i, cheminFichier);
        }

        public void DateTimePicher_ValueChanged(object sender, EventArgs e)
        {
        }

        private void lbxAnalyse_SelectedIndexChanged(object sender, EventArgs e)
        {
        }
    }
}
je pense qu'il ya de mauvaise pratique si tu en vois n'hésite pas à me corriger pour que je puisse m'améliorer ^^
ici ma classe pour les chemins
 public class AnalyseLog : AnalyseForm
    {
        private AnalyseForm analyseForm = new AnalyseForm();
        private List<string> cheminFichierOk = new List<string>();

        public List<string> IntervaleFichierGlobal(string path, DateTime dateDebut, DateTime dateFin)
        {
            string[] fichiers = Directory.GetFiles(path, "*.log", SearchOption.TopDirectoryOnly);
            DateTime[] creationTimes = new DateTime[fichiers.Length];
            for (int i = 0; i < fichiers.Length; i++)
            {
                creationTimes[i] = new FileInfo(fichiers[i]).CreationTime;
                if (creationTimes[i] >= dateDebut && creationTimes[i] <= dateFin)
                {
                    cheminFichierOk.Add(fichiers[i].ToString());
                }
            }
            return cheminFichierOk;
        }
    }
ici je fait le trie dans mes fichiers
internal class LogParse
    {
        public DateTime Datation { get; set; }
        public string Identificateur { get; set; }
        public string Module { get; set; }
        public string Type { get; set; }
        public string Info { get; set; }
        public string Details { get; set; }

        public static LogParse Parse(string lignes, string nomFichier)
        {
            if (nomFichier.StartsWith("Logis"))
            {
                string[] ligneArray = lignes.Split('\t'); //sépare les chaînes à partir
                Match m = Regex.Match(lignes, @"(?<mois>\d\d?)?/(?<jour>\d\d?)?/(?<annee>\d{4})?\s+(?<heure>\d\d?)?:(?<minute>\d\d?)?:(?<seconde>\d\d?)?\s+(?<ampm>[AP]M)?:(?<ms>\d{1,3})?");
                if (m.Success)
                {
                    int jour = int.Parse(m.Groups["jour"].Value);
                    int mois = int.Parse(m.Groups["mois"].Value);
                    int annee = int.Parse(m.Groups["annee"].Value);
                    int heure = int.Parse(m.Groups["heure"].Value);
                    int minute = int.Parse(m.Groups["minute"].Value);
                    int secondes = int.Parse(m.Groups["seconde"].Value);

                    string MS = m.Groups["ms"].Value;
                    int ms = 0;
                    if (!string.IsNullOrWhiteSpace(MS))
                    {
                        ms = int.Parse(MS);
                        if (MS.Length == 1)
                            ms *= 100;
                        else if (MS.Length == 2)
                            ms *= 10;
                    }
                    DateTime date = new DateTime(annee, mois, jour, heure, minute, secondes, ms);
                    if (m.Groups["ampm"].Value == "PM")
                        date = date.AddHours(12);
                    return new LogParse
                    {
                        Datation = date,
                        Identificateur = "Nom",
                        Module = ligneArray[1],
                        Type = ligneArray[2],
                        Info = ligneArray[3],
                        Details = ligneArray[4],
                    };
                }
                return null;
            }
Messages postés
14463
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
4 juillet 2020
553
Je ne fais plus de winform depuis longtemps, et à l'époque je ne me servais pas des observablecollection.
Ça marche très bien en WPF, faut croire qu'en Winform non.

Il va me falloir un peu de temps pour étudier ton code et je ne peux pas t'en accorder avant le début de soirée.

T'en fais pas merci à toi déja ^^
Messages postés
14463
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
4 juillet 2020
553
un truc peut-être

        public void ChargerFichier(int i, List<string> cheminFichierOk)
        {
            string result;
            foreach (string chemin in cheminFichierOk)
                i++;
            for (int j = 0; j < i; j++)
            {
                IEnumerable<string> lines = File.ReadLines(cheminFichierOk[j]);
                result = Path.GetFileName(cheminFichierOk[j]);
                foreach (var item in lines)
                {
                    LogParse leLog = LogParse.Parse(item, result);
                    lesLogs.Add(leLog);
                }
            }
            lesLogs = lesLogs.OrderBy(x => x.Datation).ToList();

            dtgLog.DataSource = null; // ajoute ça

            dtgLog.DataSource = lesLogs;
        }

ça n'a rien changé malheureusement...
Messages postés
14463
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
4 juillet 2020
553
Tout à l'heure, je me suis dit qu'il allait me falloir décrypter ta méthode Parse pour me faire un fichier avec une ou 2 lignes d'exemple.
Mais non, je l'ai reconnue cette méthode!
Et donc j'avais conservé ton fichier log.

J'ai pas encore compilé et testé, dans tout ce que tu as donné, il me manque des classes, j'essaye de voir au fur et à mesure si elles ont un intérêt pour moi.
Je pense que Export et ConfigurationManager je n'en ai pas besoin.


J'ai déjà vu pleins de petits trucs qui font perdre du temps à ton traitement, mais ça on verra après

Peut-être que j'ai la raison de ton problème, mais je ne l'ai pas testé.

Tu as dérivé ton formulaire pour une méthode, donc tu as 2 classes quasi similaires.

Je pense que tu as affiché une instance de AnalyseForm, mais dans la méthode du backgroundworker c'est à une instance de AnalyseLog, mais tu ne l'affiche pas.

            DateTime dateDebut = this.dtpDebut.Value, dateFin = this.dtpFin.Value;
            int i = 0;
            List<string> cheminFichier;
            AnalyseLog analyseLog = new AnalyseLog();//nouvelle instance de AnalyseLog
            cheminFichier = analyseLog.IntervaleFichierGlobal(lcPath, dateDebut, dateFin);
            analyseLog.ChargerFichier(i, cheminFichier);
            cheminFichier = analyseLog.IntervaleFichierGlobal(TraficPath, dateDebut, dateFin);
            analyseLog.ChargerFichier(i, cheminFichier);

           //pas de analyseLog.Show() donc elle n'est pas visible.



Quand j'étais petit, la mer Morte n'était que malade.
George Burns
Messages postés
14463
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
4 juillet 2020
553
PS j'attends ton retour avant d'inspecter plus avant
Oui c'est ça tu as bien reconnus et j'ai réussi à comprendre cette classe j'ai progresser ^^, j'ai eu un petit trou dans ce projet et je m'y remet avec cette fois une version final à la clé. Le fichier log était un parmi tant d'autre mais certain font quelque go et d'autre d'un autre outil interne, du coup je doit afficher analyselog pour pouvoir affchier mon datagridview ?
Un problème peut aussi apparaitre on me demande d'analyser plusieurs fichiers log selon une intervalle de date (du fichier et non interne au fichier), ce qui fait que je peux me retrouver avec plusieurs millions de ligne, je pense pas qu'un windows form puisse remplir cette tâche et même si l'on trie et que l'on souhaite garder les lignes contenant uniquement erreur et warning on aurais surement trop de ligne. Du coup je sais pas si il existe une solution à cela ?
Messages postés
14463
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
4 juillet 2020
553
Un problème à la fois tu veux?

du coup je doit afficher analyselog pour pouvoir affchier mon datagridview ?

oui ou non, ça dépend de toi
Si tu veux un formulaire par fichier, disons oui, mais le datagridview de AnalyseForm va rester vide.

Pour vérifier, tu peux faire un analyseLog.Show(), voir si ça s'affiche bien dans un formulaire par fichier et après en fonction de ce que préfèrerais voir on avise.
Yes^^
Un form par fichier je suis pas sur que ça sois la solution je peux me retrouver avec une 20aine de fichier facilement, le même form est plus envisageable au vu de la demande.
Messages postés
14463
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
4 juillet 2020
553
Et donc est ce que là avec analyseLog.Show() ça s'affiche?
Non mon formulaire affiche mes contrôles mais ils sont tous blanc... j'ai surement du me louper j'ai fait comme ça
DateTime dateDebut = this.dtpDebut.Value, dateFin = this.dtpFin.Value;
            int i = 0;
            List<string> cheminFichier;
            AnalyseLog analyseLog = new AnalyseLog();
            cheminFichier = analyseLog.IntervaleFichierGlobal(lcPath, dateDebut, dateFin);
            analyseLog.ChargerFichier(i, cheminFichier);
            cheminFichier = analyseLog.IntervaleFichierGlobal(trafficPath, dateDebut, dateFin);
            analyseLog.ChargerFichier(i, cheminFichier);
            analyseLog.Show();
Messages postés
14463
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
4 juillet 2020
553
Hum, je m’y repenche dans la soirée
Messages postés
14463
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
4 juillet 2020
553
Bon j'ai fait pas mal de changements

D'abord, j'ai viré la form dérivée.
J'ai mis la méthode IntervaleFichierGlobal et private List<string> cheminFichierOk = new List<string>() dans AnalyseForm

Puisque que tu ne veux pas avoir plusieurs formulaire, elle ne présente aucun intérêt et même avec plusieurs formulaires, c'était très bof puisque ta forme mère restait vide.

Ensuite j'ai supprimé
              foreach (string chemin in cheminFichierOk)
                  i++;
             for (int j = 0; j < i; j++)

que j'ai remplacé par cette seule ligne
            for (int j = 0; j < cheminFichierOk.Count - i; j++)
plus concis et plus rapide à l'exécution

ensuite, j'ai viré
              string result;

et
                   result = Path.GetFileName(cheminFichierOk[j]);

et remplacé
                     LogParse leLog = LogParse.Parse(item, result);

par
LogParse leLog = LogParse.Parse(item, Path.GetFileName(cheminFichierOk[j]));



Et surtout, j'ai affecté bindé le datagridview en dehors du thread, en effet seul le thread d'affichage a le droit d'accéder à un contrôle.
Au final le code de ChargerFichier est
        public void ChargerFichier(int i, List<string> cheminFichierOk)
        {
            for (int j = 0; j < cheminFichierOk.Count - i; j++)
            {
                IEnumerable<string> lines = File.ReadLines(cheminFichierOk[j]);
                foreach (var item in lines)
                {
                    LogParse leLog = LogParse.Parse(item, Path.GetFileName(cheminFichierOk[j]));
                    lesLogs.Add(leLog);
                }
            }
            lesLogs = lesLogs.OrderBy(x => x.Datation).ToList();
        }



Et pour le binding, je me suis servi de l'évènement de fin du backgroundworker.
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            dtgLog.DataSource = lesLogs;
        }



Quand à la méthode abonnée à DoWOrk c'est "juste" adapté aux changements.
Ça c'est ce qui marche chez moi
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            DateTime dateDebut = this.dtpDebut.Value, dateFin = this.dtpFin.Value;
            int i = 0;
            List<string> cheminFichier = new List<string> { "LogisticCore300120.log" };//ça c'est pour que ça marche chez moi

            //cheminFichier = IntervaleFichierGlobal(lcPath, dateDebut, dateFin);
            ChargerFichier(i, cheminFichier);
            //cheminFichier = IntervaleFichierGlobal(TraficPath, dateDebut, dateFin);
            //ChargerFichier(i, cheminFichier);
        }


ET ce qui devrait chez toi
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            DateTime dateDebut = this.dtpDebut.Value, dateFin = this.dtpFin.Value;
            int i = 0;

            List<string> cheminFichier = cheminFichier = IntervaleFichierGlobal(lcPath, dateDebut, dateFin);
            ChargerFichier(i, cheminFichier);
            cheminFichier = IntervaleFichierGlobal(TraficPath, dateDebut, dateFin);
            ChargerFichier(i, cheminFichier);
        }
Bonne nouvelle ça fonctionne super bien, seulement pour les petits fichiers quand les fichiers sont gros ça pose problème, le processus prend 7 minutes et à la fin je reçois l'erreur comme quoi x pour la datation est null alors que le format de l'heure et des lignes du fichiers devrais être trier correctement donc je sais pas si cela est du à leur taille. Petite question aussi pour la listbox, la classe logGroup permet de la trier ?
Messages postés
14463
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
4 juillet 2020
553
Pour les gros fichiers, il est possible que ça finisse effectivement par poser problème.
Cela dit je me serais plutôt attendu à un OutOfMemory ou un StackOverFlow.
Donc la date null pourrait avoir une autre raison.
Peux tu poster une capture d'écran

Petite question aussi pour la listbox, la classe logGroup permet de la trier
je n'ai pas vu de listbox dans le code que tu m'as donné, mais tu peux trier la liste lesLogs avec la méthode OrderBy
lesLogs = lesLogs.OrderBy(x => x.Datation).ToList();

Et l'erreur : System.NullReferenceException : 'La référence d'objet n'est pas définie à une instance d'un objet' x a été null.

Et pour la list box je veux au préalable choisir ce que je vais afficher, (Erreur, Warning, Info) mais dans ceux la il y avais les logs que toi tu avais affichés tous séparément, j'aimerai les encapsuler ex: N_ERREUR ce retrouve dans Erreur qui pourrait être dans ma list box mais seulement si je l'ai demander avant, donc je pense que ça limiterait grandement l'affichage et donc l'apparition d'erreur OutOfMemory ou StackOverFlow?