【问题标题】:How to bind nested list to datagridview in winforms如何在winforms中将嵌套列表绑定到datagridview
【发布时间】:2020-12-13 13:45:22
【问题描述】:

我正在以 Windows 形式创建应用程序。下面提到的是我要绑定到 DataGridView 的列表的结构。我有主列表(学生),在主列表中,我有要绑定到 DataGrid 视图的子列表(书)。因此,主列表将具有 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; }
}

每当我将列表绑定到数据网格视图时,我只会在网格视图行中获取 Id 和 Name 而不是 lstBk。如何在数据网格视图中获取 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;

【问题讨论】:

  • 原因是网格不知道如何将多个Books添加到网格中的“单个”单元格中。您需要“展平”图书列表。或者使用带有两个网格的主从结构。

标签: c# winforms datagridview bind


【解决方案1】:

一种可能的解决方案是“扁平化”Book 列表。如果我们重写 Books ToString 方法以输出书籍 IDName... 然后我们可以向 Student 类添加一个属性,该属性从所有 Books 中创建单个字符串名单。像……

图书课……

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

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

然后在 Student Class 中创建一个新的string 属性ListOfBooks。这将显示在网格中。有点像...

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);
    }
  }
}

这会将列表中的所有书籍放入网格中的单个单元格中。如果单元格中的数据太多,那么我建议使用带有两个网格的主从细节。一个供学生使用,另一个用于在“学生/硕士”网格中显示“选定”学生的书籍。

使用具有两个网格的 Master-Detail。

创建一个新的 winforms 项目,将几个 DataGridViews 拖放到表单上,下面的代码应该演示一种使用您发布的类实现 Master-Detail 的方法。

在这种情况下,除了 Student 类中添加的 ListOfBooks 属性之外,显然不需要 Book ToString 覆盖。它们可能看起来像原始帖子......

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; }
}

当用户“选择”“学生/硕士”网格中的不同单元格时,我们需要一些机制来“发出信号”。为此,我们将连接网格SelectionChanged 事件。在这种情况下,代码将网格中选定的Student“投射”到Student 对象,然后使用Students lstBk 列表显示到“书籍/详细信息”网格中。此事件可能如下所示...

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

加载网格时,在大多数情况下,使用主网格中的第一行填充详细信息网格,这是默认选择的单元格。

为了完成此示例,将 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 };
}

我希望这是有道理的。

【讨论】:

  • 我使用了 dataGridView1_SelectionChanged() 并设法使事情顺利进行。感谢您的评论。
猜你喜欢
  • 2012-02-12
  • 2011-12-29
  • 2011-09-15
  • 2010-11-16
  • 2010-10-15
  • 2017-08-30
  • 1970-01-01
  • 1970-01-01
  • 2011-04-21
相关资源
最近更新 更多