これに何日も取り組んだ後、私はこの問題を自分で解決することができました。私がしたことは次のとおりでした;
私の元の子クラスでは、MemberCodeとElementCodeは、基本的に列名が何であるかを示す一意のキーを作成します。そこで、これをさらに一歩進めて、「Column_Name」を追加しました。
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に割り当て、列を生成するだけで、動的データが抽出され、フラット化され、必要な方法で表示されます。