我正在创建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;
一个可能的解决方案是“扁平化”book
列表。如果重写books
toString
方法以输出图书id
和name
.。。然后,我们可以向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
属性之外,显然不需要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; }
}
当用户在“学生/主”网格中“选择”一个不同的单元格时,我们将需要一些机制来“发信号”。为此,我们将连接gridsSelectionChanged
事件。在这种情况下,代码将网格中选定的student
“强制转换”为student
对象,然后使用students
lstbk
列表显示到“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 };
}
我希望这说得通。