简体   繁体   English

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

[英]Problem in databinding Array data to DataGridView in c#

I have been binding short data to DataGridView in C# Winforms.我一直在 C# Winforms 中将短数据绑定到 DataGridView。 However, I need to bind long string array with size 75 to DataGridView.但是,我需要将大小为 75 的长字符串数组绑定到 DataGridView。 My data list class consists of 6 individual variables with get and set and array of string which I have defined get and set properties.我的数据列表类由 6 个单独的变量组成,其中包含 get 和 set 以及我定义了 get 和 set 属性的字符串数组。 The individual variables are displayed but the array of strings is not displayed in DataGridView.显示单个变量,但字符串数组未显示在 DataGridView 中。 In debug, I checked the data source of DataGridView and it seems ok.在调试中,我检查了 DataGridView 的数据源,似乎没问题。 How can I display binded array in gridview.如何在 gridview 中显示绑定数组。

Below is my source code to populate DataGridView named Logview下面是我填充名为 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();
        }
    }

Below is LogList class下面是 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;
        }
    }

Project, date/time, Qty, Pass, Fail, Result is displayed.显示项目、日期/时间、数量、通过、失败、结果。 But partlist array is not displayed.但不显示 partlist 数组。

在此处输入图像描述

Your data list class consists of 6 individual variables with get and set , and an array of string.您的数据列表类由 6 个带有getset的单独变量和一个字符串数组组成。 Your question is about the variables are displayed but the array of strings is not .你的问题是关于变量被显示但字符串数组不是

Here's what has worked for me (similar to the excellent suggestion by JohnG) for displaying the string array.这是显示字符串数组的方法(类似于 JohnG 的出色建议)。 What I'm doing here is taking a DataGridView and dropping in my main form without changing any settings (other than to Dock it).我在这里所做的是采用DataGridView并在我的主窗体中放置而不更改任何设置(除了Dock它)。 Given the default settings, the LogList class (shown here in a minimal reproducible example of 1 variable and 1 array of strings) is defined with a public string property named PartList and with this basic implementation:给定默认设置, 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);
}

To autoconfigure the DataGridView with Product and PartList columns, here is an example initializer method that sets the DataSource and adds the first three items as a test:要使用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;

}

After running this code, the DGV looks like this:运行此代码后,DGV 如下所示:

DGV

With the mouse hovered over the item all 75 "parts" can be viewed.鼠标悬停在项目上时,可以查看所有 75 个“部分”。

悬停的工具提示

One last thing - I notice you have some methods to assign a new partList[] of perhaps change an individual part at a specified index.最后一件事 - 我注意到您有一些方法可以分配一个新的 partList[] ,或者更改指定索引处的单个部分。 (I didn't show them in the minimal sample but for sure you'll want things like that). (我没有在最小样本中展示它们,但你肯定会想要这样的东西)。 You probably know this but make sure to call dataGridView1.Refresh after altering properties of an existing row/ LogList object so that the view will reflect the changes.您可能知道这一点,但请确保在更改现有行/ LogList对象的属性后调用dataGridView1.Refresh ,以便视图反映更改。

I hope there's something here that offers a few ideas to achieve the outcome you want.我希望这里有一些东西可以提供一些想法来实现你想要的结果。

To supplement IVSoftware's answer, below is an example using two grids in a master-detail scenario.为了补充 IVSoftware 的答案,下面是在主从场景中使用两个网格的示例。

One issue I would have with your current approach, is that it uses an Array for the “parts list.”对于您当前的方法,我会遇到的一个问题是,它使用数组作为“部件列表”。 Currently this is a string array, and that isn't going to work if we want to display it in a grid.目前这是一个string数组,如果我们想在网格中显示它,那是行不通的。 Fortunately, there are a few easy ways we can get the data to display as we want.幸运的是,有一些简单的方法可以让我们根据需要显示数据。

One simple solution is to create a “wrapper” Class for the string .一个简单的解决方案是为string创建一个“包装”类。 I will call this Class Part .我将称之为 Class Part I added a simple int ID property and the string PartName property.我添加了一个简单的int ID属性和string PartName属性。 You could easily leave out the ID and have a simple string wrapper.您可以轻松地省略 ID 并拥有一个简单的string包装器。 This simple Class may look something like…这个简单的类可能看起来像……

public class Part {
  public int ID { get; set; }
  public string PartName { get; set; }
}

This should allow the data to display correctly in the grid using just about any construct like an array, list etc.… So, we “could” change your current code to use an array of Part objects like…这应该允许使用任何结构(如数组、列表等)在网格中正确显示数据……因此,我们“可以”更改您当前的代码以使用Part对象数组,例如……

Part[] Parts = new Parts[X];

And this would work, however, if we use an array and we know for sure that each LogItem may have a different number of parts in its PartsList , then we will have to manage the array sizes.但是,如果我们使用数组并且我们确定每个LogItem在其PartsList中可能有不同数量的部分,那么这将起作用,那么我们将不得不管理数组大小。 So, a BindingList of Part objects will simplify this.因此, Part对象的BindingList将简化这一点。 The altered LogList ( LogItem ) Class is below…更改后的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>();
  }
}

So given the updated Classes, this should simplify things and we will use the same DataSource for both grids.因此,鉴于更新的类,这应该会简化事情,我们将为两个网格使用相同的DataSource This DataSource for the “master” grid will be a BindingList of LogItem objects. “主”网格的此DataSource将是LogItem对象的BindingList In the “detail” grid, we simply need to point it's DataMember property to the PartsList property of the currently selected LogItem .在“详细”网格中,我们只需将其DataMember属性指向当前选定LogItemPartsList属性。 And this would look something like…这看起来像……

dgvLogs.DataSource = LogsBL;
if (LogsBL.Count > 0) {
  dgvParts.DataMember = "PartsList";
  dgvParts.DataSource = LogsBL;
}

Below is the code to test the Classes above in a master-detail scenario with two grids.下面是在具有两个网格的主从场景中测试上述类的代码。 Create a new winform solution and drop two (2) DataGridView s on the form.创建一个新的 winform 解决方案并在表单上放置两 (2) 个DataGridView The grid on the left is dgvLogs and the grid on the right is dgvParts .左边的网格是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);
  }
}

And some test data…还有一些测试数据……

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

Hope this helps and makes sense.希望这会有所帮助并且有意义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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