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

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

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"

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,173 questions
No comments
{count} votes

Accepted answer
  1. answered 2020-04-30T07:34:57.523+00:00
    Peter Fleischer (Freelancer) 17,406 Reputation points

    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 additional answer

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

    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.