question

MMKottari-3427 avatar image
0 Votes"
MMKottari-3427 asked ·

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

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-wpf
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

PeterFleischer-3316 avatar image
1 Vote"
PeterFleischer-3316 answered ·

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 ·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi, thanks a lot . Now its working perfectly.

0 Votes 0 ·
AlexLi-MSFT avatar image
1 Vote"
AlexLi-MSFT answered ·

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.gif (140.2 KiB)
· 1 ·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

this is fantastic, This opened a new vision in me to handle my data. Once again thanks a lot. And i need a suggestion. I have multiple nested data by query from joined and unioned tables from database. To show such nested data, shall i go for multiple nested datagrid or shall i create a nested DataTemplate with lables and textblocks? Does usage of multiple datagrids can reduce to performance? Becasue i have to load diffrent "datagrid column structure in rowdetails" for diff rows from main datagrid.

0 Votes 0 ·