0

I have 3 Classes :

First one is Student:

public class Student
{
    public int StudentID  { get; set;}

    public string Name  { get; set;}

    public DateTime BirthDate { get; set;}

    public ICollection<StudentToCourse> StudentToCourses { get; set; }

    public Student()
    {
        StudentToCourses = new List<StudentToCourse>();
    }
}

Then Course:

    public class Course
{
    public int CourseID { get; set; }

    public string CourseName { get; set; }

    public ICollection<StudentToCourse> StudentToCourses { get; set; }


    public Course()
    {
        StudentToCourses = new List<StudentToCourse>();
    }

}

And Relation/Intermediate Class with additional properties StudentToCourse:

    public class StudentToCourse
{
    [Key, Column(Order = 0)]
    public int StudentID { get; set; }
    [Key, Column(Order = 1)]
    public int CourseID { get; set; }
    [Key, Column(Order = 2)]
    public DateTime Date { get; set; }

    public virtual Student Student { get; set; }

    public virtual Course Course { get; set; }

    public int Grade { get; set; }

}

What i try to achieve is , to display [in the data grid] each student with its id , name and birthdate, when user select specific student, data grid should display RowDetailsTemplate with courses and related grades , specific to that student. So far it displays grades / dates for each student in RowDetailsTemplate , but it doesn't display name for each course [Courses is the collection by itself]

Here is the Xaml code:

<DataGrid Grid.Column="0" ItemsSource="{Binding StudentsList}"  IsSynchronizedWithCurrentItem="True" AutoGenerateColumns="False">


<DataGrid.Columns>
    <DataGridTextColumn Header="ID" Binding="{Binding StudentID}"/>
    <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
    <DataGridTextColumn Header="BirthDate" Binding="{Binding BirthDate}"/>
</DataGrid.Columns>

<DataGrid.RowDetailsTemplate>

    <DataTemplate>

        <DataGrid ItemsSource="{Binding Path=StudentsToCourses}" AutoGenerateColumns="False">


            <DataGrid.Columns>


                <DataGridTemplateColumn Header="Course">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ListBox ItemsSource="{Binding Path=Courses}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

                <DataGridTextColumn Header="Grade" Binding="{Binding Path=Grade}" Foreground="Blue"/>
                <DataGridTextColumn Header="Date" Binding="{Binding Path=Date}" Foreground="Blue"/>

            </DataGrid.Columns>

        </DataGrid>

    </DataTemplate>

</DataGrid.RowDetailsTemplate>

To be more clear Each Student Has StudentToCourses Collection , Which Has Grade Property, Date Property And Collection of Courses, which in turns has CourseName Property . I need to display [In RowDetailsTemplate] Course Name | Grade | Date for each selected student from the DataGrid.

I'll appreciate any help.

EDIT: Here Is my database tables:

I have 3 Tables:

Courses:

CREATE TABLE [dbo].[Courses]
(
[CourseID] INT NOT NULL PRIMARY KEY IDENTITY,
[CourseName] NVARCHAR(100) NOT NULL,
)

Students:

CREATE TABLE [dbo].[Students]
(
[StudentID] INT NOT NULL PRIMARY KEY IDENTITY,
[Name] NVARCHAR(50) NOT NULL,
[BirthDate] DATETIME NOT NULL,
)

Relation Table StudentsToCourses:

CREATE TABLE [dbo].[StudentsToCourses]
(
[StudentID] INT REFERENCES Students(StudentID) NOT NULL,
[CourseID] INT REFERENCES Courses(CourseID) NOT NULL,
[Date] DATETIME NOT NULL,
[Grade] INT NOT NULL,
PRIMARY KEY (StudentID, CourseID, Date) 
)
Konrud
  • 1,114
  • 9
  • 19

2 Answers2

0

Stop what you are doing because you are doing it wrong and will cause yourself problems if you continue. We don't map database tables to code classes column for property, or not exactly at least. For example, if a Students database table has a foreign key to a Courses table, then you add a Course property of type Course to your Student class.

Continuing this example, if you have a StudentCourses joining table which means that each Course can have more than one Student and each Student can have more than one Course, then you add a Courses collection property to your Student class and a Students collection property to your Course class.

Now you might think 'how can that be?', but the fact is that your UIs will focus on either the Student or the Course and so there is no need to fully populate all of these properties all of the time... you just populate what you need for the particular view that you're working on. Once you have done that, your Binding Paths will be much simpler and you should be able to manage them on your own.

Sheridan
  • 68,826
  • 24
  • 143
  • 183
  • These classes were constructed automatically be Entity Framework, i used DataBase First-approach. I can't change them. – Konrud Sep 05 '14 at 11:33
  • Wow, that's shocking... trust Microsoft! Although, you *could* still change them for an easier life, but I'll leave that up to you. – Sheridan Sep 05 '14 at 11:53
  • I tried to do this [my way](http://stackoverflow.com/questions/25652078/database-first-approach-in-entity-framework-without-auto-generated-code), but it doesn't work. – Konrud Sep 05 '14 at 11:58
  • That `StudentToCourse` object is terrible... why does it have a `StudentID` *and* a `Student` property?? Surely the `Id` property belongs inside the `Student` class? The same for the `Course` class and the `CourseId` property... and really that class shouldn't even exist if you were to follow my advice above. Still, it's your choice, but if it were me, I'd delete *all* of that code and create my database and classes manually, the old fashioned way. – Sheridan Sep 05 '14 at 12:01
  • I appreciate your answer, but it doesn't seem right from database development perspectives, here you have to have third part / intermediate table, i think. – Konrud Sep 05 '14 at 12:20
0

In your RowDetailsTemplate, remove the course DataGridTemplateColumn and replace it with this:

<DataGridTextColumn Header="Course" Binding="{Binding Path=Course.CourseName}" Foreground="Blue"/>
J.H.
  • 4,232
  • 1
  • 18
  • 16
  • Courses is a Collection , And it can't be references as Course.CourseName . – Konrud Sep 05 '14 at 14:39
  • Course is a property of StudentToCourse. – J.H. Sep 05 '14 at 14:40
  • No way? Uh, yes way. In EF, when you have a relation between tables it creates a navigation property (in this case, StudentToCourse has a Course and a Student navigation property). When you reference those properties, EF automatically gets the object from the database (in this case, the Course entity that has the CourseID in the selected StudentToCourse). XAML allows you to reference properties of an object (so, Course.CourseName). And you're welcome :) – J.H. Sep 05 '14 at 14:59