繁体   English   中英

c#中将数组数据绑定到DataGridView的问题

[英]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 个带有getset的单独变量和一个字符串数组组成。 你的问题是关于变量被显示但字符串数组不是

这是显示字符串数组的方法(类似于 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);
}

要使用ProductPartList列自动配置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 如下所示:

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属性指向当前选定LogItemPartsList属性。 这看起来像……

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM