Sau nhiều ngày làm việc về vấn đề này, tôi đã tự giải quyết được vấn đề này. Những gì tôi đã làm là như sau;
Trong lớp con ban đầu của tôi thì Mã thành viên và Mã yếu tố tạo một khóa duy nhất cho biết về cơ bản tên cột là gì. Vì vậy, tôi đã thực hiện thêm bước này và thêm "Column_Name" để tôi có
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; }
}
Điều này rõ ràng cũng được phản ánh trong bảng cơ sở dữ liệu của tôi.
SQL của tôi để trích xuất dữ liệu sau đó trông như thế này;
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
đặt hàng bởi UniqueID trước tiên là rất quan trọng để đảm bảo các bản ghi theo đúng thứ tự để xử lý sau này.
Tôi sẽ sử dụng một dynamic
và một ExpandoObject()
để lưu trữ dữ liệu.
Vì vậy, tôi lặp lại kết quả để chuyển đổi kết quả sql thành cấu trúc này như sau;
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
Sau đó, tôi có thông tin của mình được lưu trữ động theo cách cố định mà tôi yêu cầu.
Bây giờ vấn đề tiếp theo là ObjectListView mà tôi muốn sử dụng. Điều này không thể chấp nhận các loại động như vậy.
Vì vậy, tôi đã có thông tin được lưu trữ trong mã của mình như tôi muốn, nhưng tôi vẫn không thể hiển thị thông tin đó theo yêu cầu.
Giải pháp là sử dụng một biến thể của ObjectListView
được gọi là DataListView
. Đây thực sự là điều khiển tương tự nhưng có thể bị ràng buộc dữ liệu. Một giải pháp thay thế khác cũng sẽ là sử dụng DatagridView, nhưng tôi muốn sử dụng ObjectListView vì những lý do khác.
Vì vậy, bây giờ tôi phải chuyển đổi dữ liệu động của mình thành Nguồn dữ liệu. Điều này tôi đã làm như sau;
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);
}
Sau đó, tôi chỉ cần gán nguồn dữ liệu của mình cho DataListView, tạo các cột và này trước khi tôi có dữ liệu động của mình được trích xuất, làm phẳng và hiển thị theo cách tôi yêu cầu.