简体   繁体   English

如何在winforms中将嵌套列表绑定到datagridview

[英]How to bind nested list to datagridview in winforms

I am creating app in windows form.我正在以 windows 形式创建应用程序。 Below mentioned is structure of my list that I am going to bind to DataGridView.下面提到的是我要绑定到 DataGridView 的列表的结构。 I have main list(Student) and inside main list, I have child list(Book) that is to be bind to DataGrid View.我有主列表(学生),在主列表中,我有要绑定到 DataGrid 视图的子列表(书)。 So, main list will have Id(int), Name(string) and lstBk(list which is child list).因此,主列表将有 Id(int)、Name(string) 和 lstBk(list 这是子列表)。

public class Student
{
    public int ID { get; set; }
    public string Name { get; set; }
    public List<Book> lstBk { get; set; }
}

public class Book
{
    public int ID { get; set; }

    public string Name{ get; set; }
}

Whenever I bind list to datagrid view, I am getting Id and Name only but not lstBk in grid view row.每当我将列表绑定到数据网格视图时,我只会在网格视图行中获取 Id 和 Name 而不是 lstBk。 How do I get lstBk after ID and Name in datagrid view?如何在数据网格视图中获取 ID 和名称后的 lstBk?

List<Book> lst = new List<Book>();            
lst.Add(new Book() { ID= 1, Name ="Book 1" } );
lst.Add(new Book() { ID = 2, Name = "Book 2" });
lst.Add(new Book() { ID = 3, Name = "Book 3" });
        
List<Student> lstUD = new List<Student>();
lstUD.Add(new Student() { ID = 1,  Name = "First Name1", lstBk = lst });
lstUD.Add(new Student() { ID = 2,  Name = "First Name2", lstBk = lst });
        
dataGridView1.DataSource = lstUD;

One possible solution is to “flatten” the Book list.一种可能的解决方案是“展平” Book列表。 If we override the Books ToString method to output the books ID and Name ... then we could then add a property to the Student class that creates a single string from all the Books in the list.如果我们将Books ToString方法重写为 output 书籍IDName ......然后我们可以向Student class 添加一个属性,该属性从列表中的所有Books创建单个字符串。 Something like…就像是…

Book Class…书课…

public class Book {
  public int ID { get; set; }
  public string Name { get; set; }

  public override string ToString() {
   return ID + " - " + Name;
  }
}

Then create a new string property ListOfBooks in the Student Class.然后在 Student Class 中创建一个新的string属性ListOfBooks This will get shown in the grid.这将显示在网格中。 Something like...就像是...

public class Student {
  public int ID { get; set; }
  public string Name { get; set; }
  public List<Book> lstBk { get; set; }

  public string ListOfBooks {
    get {
      return string.Join(", ", lstBk);
    }
  }
}

This will put all the books from the list into a single cell in the grid.这会将列表中的所有书籍放入网格中的单个单元格中。 If there is too much data in the cell, then I would suggest using a master-detail with two grids.如果单元格中的数据太多,那么我建议使用带有两个网格的主从细节。 One for the student and another to display the books from the “selected” student in the “student/Master” grid.一个供学生使用,另一个用于在“学生/硕士”网格中显示“选定”学生的书籍。

在此处输入图像描述

Using a Master-Detail with two grids.使用带有两个网格的 Master-Detail。

Create a new winforms project, drop a couple of DataGridView s onto the form and the code below should demonstrate one way to implement a Master-Detail using the classes you have posted.创建一个新的 winforms 项目,将几个DataGridView拖放到表单上,下面的代码应该演示一种使用您发布的类实现 Master-Detail 的方法。

在此处输入图像描述

In this case, the Book ToString override is obviously not needed in addition to the added ListOfBooks property in the Student class.在这种情况下,除了Student class 中添加的ListOfBooks属性之外,显然不需要Book ToString覆盖。 They may look like the original post…它们可能看起来像原来的帖子……

public class Book {
  public int ID { get; set; }
  public string Name { get; set; }
}

public class Student {
  public int ID { get; set; }
  public string Name { get; set; }
  public List<Book> lstBk { get; set; }
}

We will need some mechanism to “signal” when the user “selects” a different cell in the “Student/Master” grid.当用户“选择”“学生/硕士”网格中的不同单元格时,我们将需要一些机制来“发出信号”。 For this, we will wire up the grids SelectionChanged event.为此,我们将连接网格SelectionChanged事件。 In that event, the code "cast" the selected Student in the grid to a Student object, then uses the Students lstBk list to display into the “Book/Details” grid.在这种情况下,代码将网格中选定的Student “投射”到Student object,然后使用Students lstBk列表显示到“书籍/详细信息”网格中。 This event may look something like below…此事件可能如下所示...

private void dataGridView1_SelectionChanged(object sender, EventArgs e) {
  Student student = (Student)dataGridView1.CurrentRow.DataBoundItem;
  dataGridView2.DataSource = student.lstBk;
}

When the grids are loaded, the details grid is filled using the first row in the master grid as in most cases, this is the default selected cell.加载网格时,在大多数情况下,使用主网格中的第一行填充详细信息网格,这是默认选择的单元格。

To complete this example, 10 Students are added to the “Student/Master” grid such that each student has a random number of books between 1 and 6.为了完成这个示例,将 10 名Students添加到“学生/硕士”网格中,这样每个学生都有 1 到 6 本书之间的随机数量。

List<Student> AllStudents;
Random rand;

public Form1() {
  InitializeComponent();
  dataGridView1.SelectionChanged += new EventHandler(dataGridView1_SelectionChanged);
  AllStudents = new List<Student>();
  rand = new Random();
}

private void Form1_Load(object sender, EventArgs e) {
  for (int i = 1; i < 11; i++) {
    AllStudents.Add(GetStudent(i, "Student_" + i + 1));
  }
  dataGridView1.DataSource = AllStudents;
  dataGridView2.DataSource = AllStudents[0].lstBk;
}

private Student GetStudent(int studentID, string name) {
  int numberOfBooks = rand.Next(1, 7);
  int bookNumber;
  List<Book> books = new List<Book>();
  for (int i = 0; i < numberOfBooks; i++) {
    bookNumber = rand.Next(1, 10000);
    books.Add(new Book { ID = bookNumber, Name = "Book" + bookNumber });
  }
  return new Student { ID = studentID, Name = name, lstBk = books };
}

I hope this makes sense.我希望这是有道理的。

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

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