[英]Problem in databinding Array data to DataGridView in c#
我一直在 C# Winforms 中将短数据绑定到 DataGridView。 但是,我需要将大小为 75 的长字符串数组绑定到 DataGridView。 我的数据列表类由 6 个单独的变量组成,其中包含 get 和 set 以及我定义了 get 和 set 属性的字符串数组。 显示单个变量,但字符串数组未显示在 DataGridView 中。 在调试中,我检查了 DataGridView 的数据源,似乎没问题。 如何在 gridview 中显示绑定数组。
下面是我填充名为 Logview 的 DataGridView 的源代码
public void populateLogData(string path)
{
StreamReader sr = null;
BindingList<LogList> bindLogList;
BindingSource bLogsource = new BindingSource();
List<LogList> loglist = new List<LogList>();
try
{
Logview.DataSource = null;
Logview.Rows.Clear();
Logview.Columns.Clear();
Logview.AutoGenerateColumns = true;
if (File.Exists(path))
{
try
{
sr = new StreamReader(path);
StringBuilder readline = new StringBuilder(sr.ReadLine());
if (readline.ToString() != null && readline.ToString() != "")
{
readline = new StringBuilder(sr.ReadLine());
while (readline.ToString() != null && readline.ToString() != "")
{
string[] subdata = readline.ToString().Split(',');
LogList tloglist = new LogList(subdata[0], subdata[1], subdata[2], subdata[3], subdata[4], subdata[5], max_index);
for (int i = 6; i < subdata.Length; i++)
tloglist.setPartList(i-6, subdata[i]);
loglist.Add(new LogList(subdata, subdata.Length));
readline = new StringBuilder(sr.ReadLine());
}
}
bindLogList = new BindingList<LogList>(loglist);
bLogsource.DataSource = bindLogList;
Logview.AutoGenerateColumns = true;
Logview.DataSource = bindLogList;
Logview.Columns[0].Width = 140; // project name
Logview.Columns[1].Width = 140; // data/time
Logview.Columns[2].Width = 90;
Logview.Columns[3].Width = 90;
Logview.Columns[4].Width = 90;
Logview.Columns[5].Width = 90;
// max_index is set from another part of code
for(int i = 0; i <= max_index; i++)
{
int counter = 6 + i;
Logview.Columns.Add(headertext[i], headertext[i]);
Logview.Columns[counter].Width = 90;
Logview.Columns[counter].HeaderText = headertext[i];
}
}
catch (IOException io)
{
MessageBox.Show("Error: Cannot Open log file.");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if (sr != null) sr.Close();
}
}
else
{
MessageBox.Show("Log file not found \n" + path);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
GC.Collect();
}
}
下面是 LogList 类
class LogList
{
const int max_size = 100;
private string[] holdList;
public string project { get; set; }
public string date_time { get; set; }
public string Qty { get; set; }
public string Pass { get; set; }
public string Fail { get; set; }
public string Result { get; set; }
public string[] partlist
{
get
{
return holdList;
}
set
{
holdList = value;
}
}
public LogList(string project, string date_time, string Qty, string Pass, string Fail, string Result, int partsize)
{
this.project = project;
this.date_time = date_time;
this.Qty = Qty;
this.Pass = Pass;
this.Fail = Fail;
this.Result = Result;
partlist = new string[partsize+1];
}
public void setPartList(int size, string getValue)
{
partlist[size] = getValue;
}
}
显示项目、日期/时间、数量、通过、失败、结果。 但不显示 partlist 数组。
您的数据列表类由 6 个带有get
和set
的单独变量和一个字符串数组组成。 你的问题是关于变量被显示但字符串数组不是。
这是显示字符串数组的方法(类似于 JohnG 的出色建议)。 我在这里所做的是采用DataGridView
并在我的主窗体中放置而不更改任何设置(除了Dock
它)。 给定默认设置, LogList
类(此处显示为 1 个变量和 1 个字符串数组的最小可重现示例)是使用名为PartList
的公共字符串属性和以下基本实现定义的:
class LogList
{
public LogList(string product, string[] partList)
{
Product = product;
_partList = partList;
}
public string Product { get; set; }
private string[] _partList;
public string PartList => string.Join(",", _partList);
}
要使用Product
和PartList
列自动配置DataGridView
,下面是一个示例初始化方法,它设置DataSource
并添加前三个项目作为测试:
// Set data source property once. Clear it, Add to it, but no reason to nullify it.
BindingList<LogList> DataSource { get; } = new BindingList<LogList>();
private void InitDataGridView()
{
dataGridView1.DataSource = DataSource;
// Auto config columns by adding at least one Record.
DataSource.Add(
new LogList(
product: "LMG450",
// Four parts
partList: new string[]
{
"PCT2000",
"WCT100",
"ZEL-0812LN",
"EN61000-3-3/-11",
}
));
DataSource.Add(
new LogList(
product: "LMG600N",
// Three parts
partList: new string[]
{
"LTC2280",
"BMS6815",
"ZEL-0812LN",
}
));
DataSource.Add(
new LogList(
product: "Long Array",
// 75 parts
partList: Enumerable.Range(1, 75).Select(x => $"{ x }").ToArray()
));
// Use string indexer to access columns for formatting purposes.
dataGridView1
.Columns[nameof(LogList.Product)]
.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
dataGridView1
.Columns[nameof(LogList.PartList)]
.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
运行此代码后,DGV 如下所示:
将鼠标悬停在项目上时,可以查看所有 75 个“部分”。
最后一件事 - 我注意到您有一些方法可以分配一个新的 partList[] ,或者更改指定索引处的单个部分。 (我没有在最小样本中展示它们,但你肯定会想要这样的东西)。 您可能知道这一点,但请确保在更改现有行/ LogList
对象的属性后调用dataGridView1.Refresh
,以便视图反映更改。
我希望这里有一些东西可以提供一些想法来实现你想要的结果。
为了补充 IVSoftware 的答案,下面是在主从场景中使用两个网格的示例。
对于您当前的方法,我会遇到的一个问题是,它使用数组作为“部件列表”。 目前这是一个string
数组,如果我们想在网格中显示它,那是行不通的。 幸运的是,有一些简单的方法可以让我们根据需要显示数据。
一个简单的解决方案是为string
创建一个“包装”类。 我将称之为 Class Part
。 我添加了一个简单的int ID
属性和string PartName
属性。 您可以轻松地省略 ID 并拥有一个简单的string
包装器。 这个简单的类可能看起来像……
public class Part {
public int ID { get; set; }
public string PartName { get; set; }
}
这应该允许使用任何结构(如数组、列表等)在网格中正确显示数据……因此,我们“可以”更改您当前的代码以使用Part
对象数组,例如……
Part[] Parts = new Parts[X];
但是,如果我们使用数组并且我们确定每个LogItem
在其PartsList
中可能有不同数量的部分,那么这将起作用,那么我们将不得不管理数组大小。 因此, Part
对象的BindingList
将简化这一点。 更改后的LogList
( LogItem
) 类如下……
public class LogItem {
public BindingList<Part> PartsList { get; set; }
public string Project { get; set; }
public string Date_Time { get; set; }
public string Qty { get; set; }
public string Pass { get; set; }
public string Fail { get; set; }
public string Result { get; set; }
public LogItem(string project, string date_Time, string qty, string pass, string fail, string result) {
Project = project;
Date_Time = date_Time;
Qty = qty;
Pass = pass;
Fail = fail;
Result = result;
PartsList = new BindingList<Part>();
}
}
因此,鉴于更新的类,这应该会简化事情,我们将为两个网格使用相同的DataSource
。 “主”网格的此DataSource
将是LogItem
对象的BindingList
。 在“详细”网格中,我们只需将其DataMember
属性指向当前选定LogItem
的PartsList
属性。 这看起来像……
dgvLogs.DataSource = LogsBL;
if (LogsBL.Count > 0) {
dgvParts.DataMember = "PartsList";
dgvParts.DataSource = LogsBL;
}
下面是在具有两个网格的主从场景中测试上述类的代码。 创建一个新的 winform 解决方案并在表单上放置两 (2) 个DataGridView
。 左边的网格是dgvLogs
,右边的网格是dgvParts
。
public void populateLogData(string path) {
BindingList<LogItem> LogsBL = new BindingList<LogItem>();
string currentLine;
if (File.Exists(path)) {
try {
using (StreamReader sr = new StreamReader(path)) {
LogItem tempLogItem;
currentLine = sr.ReadLine(); // <- header row - ignoring
currentLine = sr.ReadLine();
while (currentLine != null) {
if (!string.IsNullOrEmpty(currentLine)) {
string[] splitArray = currentLine.Split(',');
if (splitArray.Length >= 6) {
tempLogItem = new LogItem(splitArray[0], splitArray[1], splitArray[2], splitArray[3], splitArray[4], splitArray[5]);
for (int i = 6; i < splitArray.Length; i++) {
tempLogItem.PartsList.Add(new Part { ID = i, PartName = splitArray[i] });
}
LogsBL.Add(tempLogItem);
}
else {
Debug.WriteLine("DataRead Error: Not enough items to make a LogItem: " + currentLine);
}
}
else {
Debug.WriteLine("DataRead Empty row");
}
currentLine = sr.ReadLine();
}
}
dgvLogs.DataSource = LogsBL;
if (LogsBL.Count > 0) {
dgvParts.DataMember = "PartsList";
dgvParts.DataSource = LogsBL;
}
}
catch (IOException io) {
MessageBox.Show("Error: Cannot Open log file.");
}
catch (Exception ex) {
MessageBox.Show(ex.Message + " Stacktrace- " + ex.StackTrace);
}
}
else {
MessageBox.Show("Log file not found \n" + path);
}
}
还有一些测试数据……
H1,h2,h3,h4,h5,h6,h7,h8
Model: LMG600N_IF_2blablas,2022-9-6,112,61,51,Fail,p1,p3,p4,p5,p6
1,2022-9-6,2112,621,251,Pass,px4,px5,px6,px1,px2,px3
data1,2022-9-7,3456,789,123,Fail,z3,z3,z4
Model: LMG600N_IF_2blablas,2022-9-6,112,61,51,Fail
Model: LMG600N_IF_2blablas,2022-9-6,112,61,51,Fail,p1,p3,p4,p5,p6,p7,p8,p99
BadData Model: LMG600N_IF_2blablas,2022-9-6,112,61
Moxxxdel: LMG600N_IF_2blablas,2022-9-6,11x2,6x1,5x1,Fail
希望这会有所帮助并且有意义。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.