След много дни, работещи върху това, успях сам да разреша този проблем. Това, което направих, беше следното;
В моя първоначален дъщерен клас тогава MemberCode и ElementCode създават уникален ключ, който основно посочва какво е името на колоната. Така че направих това още една стъпка и добавих „Име на колона“, така че да имам
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; }
}
Това очевидно беше отразено и в моята таблица на базата данни.
Моят SQL за извличане на данните изглеждаше така;
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
подреждането първо от UniqueID е от решаващо значение, за да се гарантира, че записите са в правилния ред за последваща обработка.
Бих използвал dynamic
и ExpandoObject()
за съхраняване на данните.
Така че преглеждам резултата, за да конвертирам sql резултата в тази структура, както следва;
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
Тогава информацията ми се съхранява динамично по плоския начин, който ми е необходим.
Сега следващият проблем беше ObjectListView, който исках да използвам. Това не може да приеме такива динамични типове.
Така че имах информацията, съхранена в моя код, както исках, но все още не можех да я покажа, както се изискваше.
Решението беше да се използва вариант на ObjectListView
известен като DataListView
. Това всъщност е същата контрола, но може да бъде обвързана с данни. Друга алтернатива също би била използването на DatagridView, но исках да се придържам към ObjectListView по други причини.
Така че сега трябваше да конвертирам моите динамични данни в източник на данни. Това направих по следния начин;
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);
}
След това просто присвоявам своя източник на данни към DataListView, генерирам колоните и хей, сега имам извлечени, изравнени и показани както искам, моите динамични данни.