Afficher dans un DataGridView à partir d'une classe
Utilisateur anonyme -
Merci à vous ^^
- Afficher dans un DataGridView à partir d'une classe
- Creer un groupe whatsapp a partir d'un autre groupe - Guide
- Créer une icone à partir d'une image - Guide
- Comment faire une recherche à partir d'une photo - Guide
- Dans le fichier, générez ce tableau automatiquement (tableau croisé dynamique ou table de pilote) à partir des quatre premières colonnes. - Guide
- Word afficher les commentaires dans la marge - Guide
38 réponses
- 1
- 2
L’affichage dans un DataGrid d'un grand volume de lignes issues d'un fichier texte, tout en gérant la mémoire et les performances, constitue la problématique centrale. Des échanges préconisent de traiter le fichier par morceaux et de mesurer la taille intermédiaire, par exemple en écrivant un fichier de test avec les premières 2 millions de lignes pour estimer le seuil mémoire. D'autres évoquent le binding du DataGrid après analyse des logs (par exemple dtgLog.DataSource = lesLogs) et la gestion des erreurs, avec des options d'affichage par fichier sur une forme séparée. En cas de gros volumes, une option consiste à évaluer l'utilisation d'une forme dédiée à l'analyse et à exécuter le chargement en arrière-plan pour limiter les pics mémoire.
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
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 ?
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;
return new LogParse
{
Datation = date,
Identificateur = "Nom",
Module = ligneArray[1],
Type = ligneArray[2],
Info = ligneArray[3],
Details = ligneArray[4],
};
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre questionce 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);
}
}
MonDatagridview.DataSource = lesLogs;
Ou
LogParseBindingSource.DataSource = lesLogs;
?
dtgLog.DataSource = lesLogs;
je sais pas si c'est important mais je passe par un BackGroundWorker
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
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;
}
}
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;
}
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;
}
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.
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.
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();
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);
}
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 trierje 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?
- 1
- 2