Après de nombreux jours de travail sur ce problème, j'ai réussi à résoudre ce problème moi-même. Ce que j'ai fait était le suivant ;
Dans ma classe enfant d'origine, MemberCode et ElementCode forment une clé unique qui indique essentiellement le nom de la colonne. Je suis donc allé un peu plus loin et j'ai ajouté un "Column_Name" pour que j'aie
public class Child
{
public int MemberCode { get; set; } //Composite key
public int ElementCode { get; set; } //Composite key
public string Column_Name { get; set; } //Unique. Alternative Key
public Object Data { get; set; }
}
Cela se reflétait évidemment également dans ma table de base de données.
Mon SQL pour extraire les données ressemblait alors à ceci ;
select p.UniqueID, p.LoadTime, p.reference, c.MemberCode, c.ElementCode , c.column_name, c.Data
from parent as p, child as c
where p.UniqueID = c.UniqueID
//aditional filter criteria
ORDER BY p.UniqueID, MemberCode, ElementCode
le classement par UniqueID est essentiel pour s'assurer que les enregistrements sont dans le bon ordre pour un traitement ultérieur.
Le j'utiliserais un dynamic
et un ExpandoObject()
pour stocker les données.
J'itère donc sur le résultat pour convertir le résultat sql dans cette structure comme suit ;
List<dynamic> allRecords = new List<dynamic>(); //A list of all my records
List<dynamic> singleRecord = null; //A list representing just a single record
bool first = true; //Needed for execution of the first iteration only
int lastId = 0; //id of the last unique record
foreach (DataRow row in args.GetDataSet.Tables[0].Rows)
{
int newID = Convert.ToInt32(row["UniqueID"]); //get the current record unique id
if (newID != lastId) //If new record then get header/parent information
{
if (!first)
allRecords.Add(singleRecord); //store the last record
else
first = false;
//new object
singleRecord = new List<dynamic>();
//get parent information and store it
dynamic head = new ExpandoObject();
head.Column_name = "UniqueID";
head.UDS_Data = row["UniqueID"].ToString();
singleRecord.Add(head);
head = new ExpandoObject();
head.Column_name = "LoadTime";
head.UDS_Data = row["LoadTime"].ToString();
singleRecord.Add(head);
head = new ExpandoObject();
head.Column_name = "reference";
head.UDS_Data = row["reference"].ToString();
singleRecord.Add(head);
}
//get child information and store it. One row at a time
dynamic record = new ExpandoObject();
record.Column_name = row["column_name"].ToString();
record.UDS_Data = row["data"].ToString();
singleRecord.Add(record);
lastId = newID; //store the last id
}
allRecords.Add(singleRecord); //stores the last complete record
Ensuite, mes informations sont stockées dynamiquement de la manière plate dont j'ai besoin.
Maintenant, le problème suivant était l'ObjectListView que je voulais utiliser. Cela ne pouvait pas accepter de tels types dynamiques.
J'avais donc les informations stockées dans mon code comme je le voulais, mais je ne pouvais toujours pas les afficher comme il le fallait.
La solution était d'utiliser une variante de ObjectListView
connu sous le nom de DataListView
. Il s'agit en fait du même contrôle mais peut être lié aux données. Une autre alternative serait également d'utiliser un DatagridView, mais je voulais m'en tenir à ObjectListView pour d'autres raisons.
Alors maintenant, je devais convertir mes données dynamiques en une source de données. Ce que j'ai fait comme suit ;
DataTable dt = new DataTable();
foreach (dynamic record in allRecords)
{
DataRow dr = dt.NewRow();
foreach (dynamic item in record)
{
var prop = (IDictionary<String, Object>)item;
if (!dt.Columns.Contains(prop["Column_name"].ToString()))
{
dt.Columns.Add(new DataColumn(prop["Column_name"].ToString()));
}
dr[prop["Column_name"].ToString()] = prop["UDS_Data"];
}
dt.Rows.Add(dr);
}
Ensuite, j'assigne simplement ma source de données au DataListView, génère les colonnes, et hop, mes données dynamiques sont maintenant extraites, aplaties et affichées comme je le souhaite.