通过旋转子列表将具有子列表的自定义对象(List <T>)绑定到网格

sur*_*gle 8 c# data-binding dynamic winforms

我想将一个列表绑定List<CourseDetails>/.每个CourseDetail都有一个属性StudentList类型 List<Student>.学生列表应该旋转,以便结果如下所示:

datagrid的所需布局示例

我的问题

我如何调整每个学生,StudentList以便我可以将数据绑定List<CourseDetails>到同一个.

 var courseList = List<CourseDetails>();
 courseList.Add(cd1);
 courseList.Add(cd2);
Run Code Online (Sandbox Code Playgroud)

我至少有三个问题无法解决:

  1. 如何在courseDetails的实例中透视StudentList
  2. 如何UNION两个courseDetail对象(cd1,cd2)/或n(n <13000)一起为每个学生创建一个单独的列
  3. 如何将courseDetails这样的对象绑定到xtragrid.

在Gist上演示Linqpad

一个演示linqpad程序可以在要点中找到.

课程详细信息

以下课程代表学校的课程.

public class CourseDetails{
    public int Id{ get; set;}
    public Course Course{ get; set;}
    public Teacher Teacher{get; set;}
    public Room Room{get; set;}
    public List<Student> StudentList{get; set;}
}
Run Code Online (Sandbox Code Playgroud)

清单 List<CourseDetails>

a List<CourseDetails>中的每个对象都包含一个学生列表.学生列表中有时只有少数学生(2到5个),有时每个学生列表中有15到40个学生.CourseDetails之间的学生可以重叠,但也可以是分离(不相交/不重叠)

第一个var cd1 = new CourseDetails()包含3名学生List<Student>

var cd1 = new CourseDetails(){
    Id =1 
    ,Course = new Course(){CourseId = 435, CourseName="C# Ninja"}
    ,Teacher = new Teacher(){TeacherId=48, TeacherName="J Skee"}
    ,Room = new Room(){RoomId=32, RoomName="base floor R001"}
    ,StudentList = new List<Student>(){
        new Student(){Id = 101, StudentName="Amy"}
        ,new Student(){Id = 104, StudentName="Koothrap"}
        ,new Student(){Id = 105, StudentName="Cooper"}
    }
};
Run Code Online (Sandbox Code Playgroud)

第二个var cd2 = new CourseDetails()包含2名学生List<Student>

var cd2 = new CourseDetails(){
    Id =1 
    ,Course = new Course(){CourseId = 201, CourseName="SQL Basics"}
    ,Teacher = new Teacher(){TeacherId=30, TeacherName="M Gra"}
    ,Room = new Room(){RoomId=80, RoomName="2th floor R100"}
    ,StudentList = new List<Student>(){
        new Student(){Id = 101, StudentName="Amy"}
        ,new Student(){Id = 102, StudentName="Penny"}
    }
};
Run Code Online (Sandbox Code Playgroud)

为了方便屏幕截图使用Tuple<string, string,....>但是对于网格我希望每列都有底层属性的数据类型(int,string,date,...).从第一行开始Id, Course, Teacher, Amy, ...将是网格的标题.

Sim*_*mon 3

好的,我不知道这是否可行,但是当我们将网格绑定到对象列表时,我们会执行类似的操作,然后根据用户选择的月份,我们在运行时将月份中的天数添加为列 - 并且根据应用程序中的其他数据进行填充。然而,在我看来,如果您不需要编辑数据,则可以通过在数据库中创建视图,然后简单地将视图数据作为 DataTable 返回并直接绑定到它来轻松实现。方式,方式更容易。不幸的是,我们必须编辑数据,这不是一件容易的事!

不管怎样,希望你能通过自己的努力度过难关。

  1. 您有一个课程详细信息列表,每个课程详细信息都有一个学生列表。
  2. 在设计器中创建网格,并创建将绑定到 CourseDetails 属性(ID、课程、教师、房间)的静态列
  3. 在运行时,将网格的数据源设置为课程详细信息列表。当您执行此操作时/之前,您必须从 CourseDetails 列表中提取不同的学生姓名,您可以使用 LINQ 来执行此操作(类似于 [未测试])-

var names = CourseDetails.SelectMany(c => c.StudentList).Select(s => s.Name).Distinct();

将这些列作为未绑定列添加到网格中,例如:

    //Make sure you clear existing unboundcolumns
    foreach(string name in names)
    {
       int idx = gridView.Columns.Add(new GridColumn());
       gridView.Columns[idx].Visible = true;
       gridView.Columns[idx].Tag = name;
       gridView.Columns[idx].Caption = name;
       gridView.Columns[idx].UnboundType = UnboundColumnType.Integer;
    }
Run Code Online (Sandbox Code Playgroud)

现在处理CustomUnboundColumnDatagridview 上的事件。您将需要执行与此类似的操作(不确定您想要如何匹配 - ID/名称):

    CourseDetail course = e.Row as CourseDetails;
    if (e.IsGetData)
    {
        e.Value = course.StudentList.Where(s => s.Name == e.Column.Tag.ToString()).Count();  
    }
Run Code Online (Sandbox Code Playgroud)

如果需要匹配 ID(将 ID 放入 Column.Tag 属性中):

e.Value = course.StudentList.SingleOrDefault(s => s.ID == (int)e.Column.Tag).Grade;
Run Code Online (Sandbox Code Playgroud)

或任何您需要显示的内容。显然需要进行空检查等。

希望有点帮助。仍然认为你吠错了树,但无论如何......