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

时间:2013-05-16 23:55:52

标签: c# winforms data-binding dynamic

我想将一个CourseDetails列表List<CourseDetails>绑定到 / 。每个CourseDetail都有StudentList类型的List<Student>。应该对学生列表进行调整,以使结果如下所示:

Example of desired layout of datagrid

我的问题

如何调动StudentList中的每位学生,以便我可以将List<CourseDetails>数据绑定到同一

 var courseList = List<CourseDetails>();
 courseList.Add(cd1);
 courseList.Add(cd2);

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

  1. 如何在courseDetails实例中透视StudentList
  2. 如何联合两个courseDetail对象(cd1,cd2)/或n(n&lt; 13000),为每个学生创建一个单独的列
  3. 如何将courseDetails这样的对象绑定到xtragrid。
  4. 在Gist上演示Linqpad

    demo linqpad program can be found on gist

    课程详细信息

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

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

    List<CourseDetails>

    的列表

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

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

    中的3名学生
    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"}
        }
    };
    

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

    中的2名学生
    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"}
        }
    };
    

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

2 个答案:

答案 0 :(得分:3)

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

无论如何,希望你能够顺利完成它。

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

    现在处理gridview上的CustomUnboundColumnData事件。你需要做类似的事情(不确定你想要匹配的方式 - ID /名称):

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

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

    e.Value = course.StudentList.SingleOrDefault(s => s.ID == (int)e.Column.Tag).Grade;
    

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

    希望有所帮助。仍然认为你吠叫错误的树,但无论如何......

答案 1 :(得分:1)

实际上你必须使用C#进行数据透视,因为当你想要将数据绑定(或以任何方式提供)到你的UI时 - 你的视图对象是Course(我不知道你的域对象也是是否使用某些ORM) - 从数据库中提取的数据透视数据不会(直接)帮助(编排您的UI),您应该按操作执行一些LINQ组以提取Course的列表