提问者:小点点

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


我正在创建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; }
}

每当我将list绑定到datagrid视图时,在网格视图行中只获得Id和名称,而不获得lstBk。如何在datagrid视图中获取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;

共1个答案

匿名用户

一个可能的解决方案是“扁平化”book列表。如果重写bookstoString方法以输出图书idname.。。然后,我们可以向student类添加一个属性,该属性从列表中的所有books创建一个字符串。类似于…

图书类…

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

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

然后在Student类中创建一个新的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项目,将几个DataGridView放到窗体上,下面的代码将演示使用您发布的类实现主详细信息的一种方法。

在这种情况下,除了在Student类中添加的ListOfBooks属性之外,显然不需要BookToString重写。他们可能看起来像原来的帖子…

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

当用户在“学生/主”网格中“选择”一个不同的单元格时,我们将需要一些机制来“发信号”。为此,我们将连接gridsSelectionChanged事件。在这种情况下,代码将网格中选定的student“强制转换”为student对象,然后使用studentslstbk列表显示到“book/details”网格中。这个事件可能看起来像下面这样…

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

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

为了完成此示例,将10个学生添加到“student/Master”网格中,这样每个学生都有一个介于1到7之间的随机数书籍。

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

我希望这说得通。

相关问题