2

I have StudentDB, which is just a list of Student objects, which is defined as:

 public class Student
        {
            public String StudentID { get; set; }
            public int ExtraCredit { get; set; }
            public int QtyDemerits { get; set; }
            public List<Demerits> LstDemerits = new List<Demerits>();
        }

  public class Demerits
        {
            public String TeacherID { get; set; }
            public DateTime AsOf { get; set; }
            public String Description1 { get; set; }
            public String Description2 { get; set; }
        }

I would like to compile a list of students, ordered by descending order of ExtraCredit, and see all of the student's Demerit details if they have any (i.e. TeacherID, AsOf, Description 1 & 2).

Here's my query, which is not quite yielding everything I want:

List<Student> StudentDB2 = new List<Student>();

 StudentDB2 = StudentDB.OrderByDescending(x => x.ExtraCredit).Select(r => new Student
        {
            StudentID = r.StudentID,
            ExtraCredit = r.ExtraCredit,
            QtyDemerits = r.QtyDemerits,
            LstDemerits = r.Demerits.OrderBy(c => c.TeacherID).ThenBy(d => d.AsOf).ToList()
        })
        .ToList();

dataGridView1.DataSource = StudentDB2;

When I run the code I'm only seeing 3 columns of data: StudentID, ExtraCredit, and QtyDemerits. But if QtyDemerits > 0, I'm not seeing the data in LstDemerits which should show Teacher Id and As of Date. What is wrong with my query?

MrPatterns
  • 4,184
  • 27
  • 65
  • 85

3 Answers3

2

The LstDemerits property is not being bound to the data source since it is a List<Demerits> rather than a string/int, etc.

Try making LstDemerits a string like so:

public class Student
{
    public String StudentID { get; set; }
    public int ExtraCredit { get; set; }
    public int QtyDemerits { get; set; }
    public string LstDemerits { get; set; }
}

Then write custom logic to properly render a List<Demerits> into a string.

StudentDB2 = StudentDB.OrderByDescending(x => x.ExtraCredit).Select(r => new Student
        {
            StudentID = r.StudentID,
            ExtraCredit = r.ExtraCredit,
            QtyDemerits = r.QtyDemerits,
            LstDemerits = CustomLogic(r.Demerits)
        })
        .ToList();
James Lawruk
  • 30,112
  • 19
  • 130
  • 137
1

The problem is not your query, but rather the GridView you're binding your query to. By default, GridViews display the properties of the object bound to them, but cannot display complex properties like a List. This is reasonable, as attempting to display a List as columns leads to hard questions that can't be answered generally. Take your own object as an example: you bind a List<Student> to the GridView, and suppose the GridView then creates four additional columns (one column for each field) for every Demerits in each Student's LstDemerits. That might work. But what if Demerits were assigned by multiple teachers, and so the TeacherID field was itself a List. Then the GridView might add additional columns for each TeacherID in this inner object's list. In general, this quickly becomes untenable.

One solution is given as the answer to this question. Another solution would be to build a DataTable yourself in your code behind so that you can display your objects correctly. Perhaps the easiest solution is to shove your List<Student> object into a List<Dictionary<string, string>>, with the keys being field names and values being the data from your class, with additional key-value pairs for each Demerits object in the Student's LstDemerits. However, this method offers significant disadvantages if you want to do anything with your webpage other than display you information.

In my opinion, this information would be better represented by having a secondary page - the primary page displays each Student along with the number of Demerits they have, and selecting a Student on the primary page takes you to a secondary page that displays all of that Student's Demerits.

Community
  • 1
  • 1
Zack Butcher
  • 1,046
  • 7
  • 12
0

Maybe you should try to filter for all those students who has LstDemerits .Count > 0, something like:

List<Student> StudentDB2 = new List<Student>();

 StudentDB2 = StudentDB.Where(i => i.LstDemerits.Count > 0).OrderByDescending(x => x.ExtraCredit).Select(r => new Student
        {
            StudentID = r.StudentID,
            ExtraCredit = r.ExtraCredit,
            QtyDemerits = r.QtyDemerits,
            LstDemerits = r.Demerits.OrderBy(c => c.TeacherID).ThenBy(d => d.AsOf).ToList()
        })
        .ToList();

dataGridView1.DataSource = StudentDB2;

THis way you should avoid the empty lists, that maybe are your problem at the end. I hope this helps

Oscar Bralo
  • 1,912
  • 13
  • 12
  • But I want to see all students whether or not they have demerits. I don't want to needlessly exclude students whose Demerit count = 0. Thanks. – MrPatterns Mar 17 '14 at 19:39