简体   繁体   中英

How to bind nested list to datagridview in winforms

I am creating app in windows form. Below mentioned is structure of my list that I am going to bind to DataGridView. I have main list(Student) and inside main list, I have child list(Book) that is to be bind to DataGrid View. So, main list will have Id(int), Name(string) and lstBk(list which is child 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. How do I get lstBk after ID and Name in datagrid view?

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. 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. 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. 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.

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.

在此处输入图像描述

In this case, the Book ToString override is obviously not needed in addition to the added ListOfBooks property in the Student class. 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. 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. 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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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