'WPF DataGrid doesn't display the binded values

I have a very frustrating problem with a WPF screen I am working on. This is the code:

<DataGrid Grid.Row="2" Grid.Column="2" 
                 ItemsSource="{Binding SelectedPlayer.ReportFiles}" 
                 HorizontalContentAlignment="Stretch"
                 AutoGenerateColumns="False"
                 >
                 <!--ItemTemplate="{DynamicResource reportHeader}"-->
            <DataGrid.Columns>
                <DataGridTemplateColumn Width="*">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Grid Grid.Row="1">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*"/>
                                    <ColumnDefinition Width="100"/>
                                    <ColumnDefinition Width="*"/>
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="20"/>
                                    <RowDefinition Height="*"/>
                                </Grid.RowDefinitions>
                                <TextBlock Text="{Binding Attacker}" Grid.Column="0" Grid.Row="0"/>
                                <TextBlock Text="{Binding Defender}" Grid.Column="2" Grid.Row="0"/>
                                <DataGrid ItemsSource="{Binding LeftReportSummary}"
                                                  GridLinesVisibility="None"
                                                  Height="Auto"
                                                  HeadersVisibility="None"
                                                  AutoGenerateColumns="False"
                                                  IsReadOnly="True"
                                                  Grid.Row="1" Grid.Column="0">
                                    <DataGrid.Columns>
                                        <DataGridTextColumn Binding="{Binding name}" Width="75"/>
                                        <DataGridTextColumn Binding="{Binding description}"/>
                                    </DataGrid.Columns>
                                </DataGrid>
                                <DataGrid ItemsSource="{Binding RightReportSummary}"
                                                  GridLinesVisibility="None"
                                                  Height="Auto"
                                                  HeadersVisibility="None"
                                                  AutoGenerateColumns="False"
                                                  IsReadOnly="True"
                                                  Grid.Row="1" Grid.Column="2">
                                    <DataGrid.Columns>
                                        <DataGridTextColumn Binding="{Binding name}" Width="75"/>
                                        <DataGridTextColumn Binding="{Binding description}"/>
                                    </DataGrid.Columns>
                                </DataGrid>
                            </Grid>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>

In this case, the DataGridTextColumns in the seconds DataGrid objects are not displaying anything. The appropriate number of rows is generated and I have also debugged the backend to check if the list of items is not empty (which it isn't). I tried several approaches, but none solved the issue. I would be very thankful if someone has an idea.

EDIT: Here is the VM used to back up the screen

private ObservableCollection<Player> players = new ObservableCollection<Player>();
        private Player selectedPlayer;

        public ObservableCollection<Player> Players
        {
            get => players;
            set
            {
                players = value;
                RaisePropertyChanged(nameof(Players));
                SelectedPlayer = Players.First();
            }
        }

        public Player SelectedPlayer
        {
            get => selectedPlayer;
            set
            {
                selectedPlayer = value;
                RaisePropertyChanged(nameof(SelectedPlayer));
            }
        }

        public void GetPlayers()
        {
            IList<Player> playersList = new List<Player>();
            var dirs = Directory.GetDirectories($"c:\\Logs\\Reports", "*", SearchOption.TopDirectoryOnly);
            foreach (var dir in dirs)
            {
                var dirInfo = new DirectoryInfo(dir);
                var player = new Player(dirInfo.Name);
                var battleReportFiles = Directory.GetFiles(dir, "*battle_record.txt").Select(f => new FileInfo(f));
                foreach (var battleReportFile in battleReportFiles)
                {
                    player.ReportFiles.Add(new ReportFile
                    {
                        FullFilename = battleReportFile.FullName,
                        Filename = battleReportFile.Name,
                        ParsedReport = Reader.parseReportsFromFile(battleReportFile.FullName)[0]
                    });
                }
                playersList.Add(player);
            }
            Players = new ObservableCollection<Player>(playersList);
        }

        private ReportFile selectedReportFile;
        public ReportFile SelectedReportFile
        {
            get => selectedReportFile;
            set
            {
                if (selectedReportFile == value) return;
                selectedReportFile = value;
                RaisePropertyChanged(nameof(SelectedReportFile));
            }
        }


        #region Property handling

        public event PropertyChangedEventHandler? PropertyChanged;

        private void RaisePropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    

public class Player
    {
        public string Name { get; set; }
        public IList<ReportFile> ReportFiles { get; set; }
        public int ReportCount => ReportFiles.Count;
    }


public class ReportFile
    {
        public string FullFilename { get; set; }
        public string Filename { get; set; }

        private Report parsedReport;
        public Report ParsedReport
        {
            get => parsedReport;
            set
            {
                parsedReport = value;
                parsedReport.Parse();
                var rows = ReportPrinter.PrintReportRows(parsedReport);
                leftReportSummary = new ObservableCollection<PrintRow>(rows.left);
                rightReportSummary = new ObservableCollection<PrintRow>(rows.right);
            }
        }

        public string Attacker
        {
            get
            {
                if (Filename == null || Filename.Length == 0) return "";
                return Filename.Split("--")[0];
            }
        }

        public string Defender
        {
            get
            {
                if (Filename == null || Filename.Length == 0) return "";
                return Filename.Split("__")[0].Split("--")[1];
            }
        }

        public IList<CommanderAwakening> AttackerCommanders => ParsedReport.attackCommanders;
        public IList<CommanderAwakening> DefenderCommanders => ParsedReport.defenceCommanders;

        private ObservableCollection<PrintRow> leftReportSummary = new ObservableCollection<PrintRow>();
        public ObservableCollection<PrintRow> LeftReportSummary 
        {
            get => leftReportSummary;
            set => leftReportSummary = value;
        }

        private ObservableCollection<PrintRow> rightReportSummary = new ObservableCollection<PrintRow>();
        public ObservableCollection<PrintRow> RightReportSummary
        {
            get => rightReportSummary;
            set => rightReportSummary = value;
        }
    }



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source