C# WPF How to bind a nested class to nested datagrid in “Datagrid Row-Details”?

MM Kottari 21 Reputation points
2020-04-30T04:23:39.06+00:00

How to bind data from nested classs to a nested datagrid? Why nested datagrid unable to read the class? what error i am doing?

public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public DateTime Birthday { get; set; }
        public Marks myMarks { get; set; }
    }

    public class Marks
    {
        public double English { get; set; }
        public double Maths { get; set; }
        public double Science { get; set; }
    }

Itemsource for main-datagrid "DG_myStudents"

private void Page_Loaded(object sender, RoutedEventArgs e)
{
   List<Student> myStudents = new List<Student>();

    Marks JohnMark = new Marks();
    JohnMark.English = 75;
    JohnMark.Maths = 85;
    JohnMark.Science = 95;

    Marks RichardMark = new Marks();
    RichardMark.English = 70;
    RichardMark.Maths = 80;
    RichardMark.Science = 90;

    Marks SamMark = new Marks();
    SamMark.English = 72;
    SamMark.Maths = 82;
    SamMark.Science = 92;

    myStudents.Add(new Student() { Id = 1, Name = "John Doe", Birthday = new DateTime(1971, 7, 23), myMarks = JohnMark });
    myStudents.Add(new Student() { Id = 2, Name = "Richard Doe", Birthday = new DateTime(1974, 1, 17), myMarks = RichardMark });
    myStudents.Add(new Student() { Id = 3, Name = "Sammy Doe", Birthday = new DateTime(1991, 9, 2), myMarks = SamMark });

    DG_myStudents.ItemsSource = myStudents;
}

and below is my XAML code, Am i doing any error in class structure? Please help me.

<DataGrid x:Name="DG_myStudents" RowDetailsVisibilityMode="Visible">
        <DataGrid.RowDetailsTemplate>
            <DataTemplate>
                <DataGrid x:Name="DG_myMarks" ItemsSource="{Binding myMarks}" />
            </DataTemplate>
        </DataGrid.RowDetailsTemplate>
    </DataGrid>

The nested datagrid "DG_myMarks" is not showing any data. And when i bind "myMarks" to a label tfor just to check any thing happening there, then label is showing "Marks class name" like this "MyNameSpace.myPage+Marks"

Developer technologies | Windows Presentation Foundation
0 comments No comments
{count} votes

Answer accepted by question author
  1. Peter Fleischer (former MVP) 19,341 Reputation points
    2020-04-30T07:34:57.523+00:00

    Hi, ItemsSource of DataGrid (in RowDetailsTemplate) needs collection (e.g. list). Change your code:

    private void Page_Loaded(object sender, RoutedEventArgs e)
    {
      List<Student> myStudents = new List<Student>();
    
      Marks JohnMark = new Marks();
      JohnMark.English = 75;
      JohnMark.Maths = 85;
      JohnMark.Science = 95;
    
      Marks RichardMark = new Marks();
      RichardMark.English = 70;
      RichardMark.Maths = 80;
      RichardMark.Science = 90;
    
      Marks SamMark = new Marks();
      SamMark.English = 72;
      SamMark.Maths = 82;
      SamMark.Science = 92;
    
      Student stud = new Student() { Id = 1, Name = "John Doe", Birthday = new DateTime(1971, 7, 23) };
      stud.myMarks.Add(JohnMark);
      myStudents.Add(stud);
      stud = new Student() { Id = 2, Name = "Richard Doe", Birthday = new DateTime(1974, 1, 17) };
      stud.myMarks.Add(RichardMark);
      myStudents.Add(stud);
      stud = new Student() { Id = 3, Name = "Sammy Doe", Birthday = new DateTime(1991, 9, 2) };
      stud.myMarks.Add(SamMark);
      myStudents.Add(stud);
      DG_myStudents.ItemsSource = myStudents;
    }
    
    public class Student
    {
      public int Id { get; set; }
      public string Name { get; set; }
      public DateTime Birthday { get; set; }
      public List<Marks> myMarks { get; set; } = new List<Marks>();
    }
    
    1 person found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. Alex Li-MSFT 1,096 Reputation points
    2020-04-30T07:07:20.537+00:00

    Welcome to our Microsoft Q&A platform!

    I made a example ,you can try it.

     public partial class MainWindow : Window  
        {  
            public MainWindow()  
            {  
                InitializeComponent();  
            }  
      
            private void Window_Loaded(object sender, RoutedEventArgs e)  
            {  
                List<Student> myStudents = new List<Student>();  
      
                Marks JohnMark = new Marks();  
                JohnMark.English = 75;  
                JohnMark.Maths = 85;  
                JohnMark.Science = 95;  
      
                Marks RichardMark = new Marks();  
                RichardMark.English = 70;  
                RichardMark.Maths = 80;  
                RichardMark.Science = 90;  
      
                Marks SamMark = new Marks();  
                SamMark.English = 72;  
                SamMark.Maths = 82;  
                SamMark.Science = 92;  
      
                myStudents.Add(new Student() { Id = 1, Name = "John Doe", Birthday = new DateTime(1971, 7, 23), myMarks = JohnMark });  
                myStudents.Add(new Student() { Id = 2, Name = "Richard Doe", Birthday = new DateTime(1974, 1, 17), myMarks = RichardMark });  
                myStudents.Add(new Student() { Id = 3, Name = "Sammy Doe", Birthday = new DateTime(1991, 9, 2), myMarks = SamMark });  
      
      
                DG_myStudents.ItemsSource = myStudents;  
      
                 
            }  
            private void Expander_Expanded(object sender, RoutedEventArgs e)  
            {  
                DataGridRow row = FindVisualParent<DataGridRow>(sender as Expander);  
                row.DetailsVisibility = System.Windows.Visibility.Visible;  
            }  
      
            private void Expander_Collapsed(object sender, RoutedEventArgs e)  
            {  
                DataGridRow row = FindVisualParent<DataGridRow>(sender as Expander);  
                row.DetailsVisibility = System.Windows.Visibility.Collapsed;  
            }  
            
            public T FindVisualParent<T>(DependencyObject child) where T : DependencyObject  
            {  
                DependencyObject parentObject = VisualTreeHelper.GetParent(child);  
                if (parentObject == null) return null;  
                T parent = parentObject as T;  
                if (parent != null)  
                    return parent;  
                else  
                    return FindVisualParent<T>(parentObject);  
            }  
             
      
            private void DG_myStudents_RowDetailsVisibilityChanged(object sender, DataGridRowDetailsEventArgs e)  
            {  
                 
                DataGrid MainDataGrid = sender as DataGrid;  
                var cell = MainDataGrid.CurrentCell;  
               
                Student student = (MainDataGrid.CurrentItem as Student);  
                if (student == null)  
                {  
                    return;  
                }  
                List<Marks> MarksList = new List<Marks>();  
                DataGrid DetailsDataGrid = e.DetailsElement as DataGrid;  
      
                MarksList.Add(new Marks() { English = student.myMarks.English, Maths = student.myMarks.Maths, Science = student.myMarks.Science });  
                DetailsDataGrid.ItemsSource = MarksList;  
            }  
      
      
        }  
      
        public class Student  
        {  
            public int Id { get; set; }  
            public string Name { get; set; }  
            public DateTime Birthday { get; set; }  
            public Marks myMarks { get; set; }  
        }  
      
        public class Marks  
        {  
            public double English { get; set; }  
            public double Maths { get; set; }  
            public double Science { get; set; }  
        }  
    

    xaml

      <Grid>  
            <DataGrid x:Name="DG_myStudents" RowDetailsVisibilityMode="Visible" AutoGenerateColumns="False" RowDetailsVisibilityChanged="DG_myStudents_RowDetailsVisibilityChanged" >  
                <DataGrid.Columns>  
                    <DataGridTemplateColumn Width="Auto">  
                        <DataGridTemplateColumn.CellTemplate>  
                            <DataTemplate>  
                                <Expander Width="50" Expanded="Expander_Expanded" Collapsed="Expander_Collapsed" IsExpanded="False" />  
                            </DataTemplate>  
                        </DataGridTemplateColumn.CellTemplate>  
                    </DataGridTemplateColumn>  
                    <DataGridTextColumn Header="Id" Binding="{Binding Id}" CanUserResize="False" Width="Auto"/>  
                    <DataGridTextColumn Header="Name" Binding="{Binding Name}" CanUserResize="False" Width="Auto"/>  
                    <DataGridTextColumn Header="Birthday" Binding="{Binding Birthday}" CanUserResize="False" Width="Auto"/>  
                     
                </DataGrid.Columns>  
                <DataGrid.RowDetailsTemplate>  
                    <DataTemplate>  
                        <DataGrid x:Name="DG_myMarks" IsReadOnly="True" Margin="15,8,8,8"  Width="399" AutoGenerateColumns="False" >  
                            <DataGrid.Columns>  
                                <DataGridTextColumn Header="English" Binding="{Binding English}" Width="Auto"/>  
                                <DataGridTextColumn Header="Maths" Binding="{Binding Maths}" Width="Auto"/>  
                                <DataGridTextColumn Header="Science" Binding="{Binding Science}" Width="Auto"/>  
                            </DataGrid.Columns>  
                        </DataGrid>  
                    </DataTemplate>  
                </DataGrid.RowDetailsTemplate>  
            </DataGrid>  
      
        </Grid>  
    

    7807-1.gif

    Thanks.

    1 person found this answer helpful.

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.