More on grouping. As per the previous post, display data in a table a a formatted Blazor page such that it can be saved as a PDF file for printing as certificate. Merge grouped records into one though.


As discussed in previous posts we have developed a Club Blazor Server app that includes the life cycle management of an club’s athletic records. Records are claimed by athletes. An admin manages verifying and accepting claims. The latest extension is the ability to list all records set by an athlete in any one season as a certificate with similar graphics and saved as a PDF which can then be downloaded by the athlete. This post discusses the generation of a certificate where an athlete has achieved multiple records, each of which has been achieved over multiple age groups and therefore can be merged into one entry in the table.

This pages takes as a parameter, the athlete’s Id which can be supplied by the first page selection, or from the logged in user such that an athlete can log in and generate the certificate them self. The page is only directly accessible though for a non-admin if they do have at least one record. Athletes can only generate a certificate for themselves.


This is for when the number of records is large (>25) for an athlete in one season, particularly where they are spread over multiple age groups for the same event on the same day. It is accessed from the first page as a Shift-Click. Where a record is spread over multiple age groups, on the same day, instead of grouping them by using the same background, they are concertinaed into one row with of the all ages listed together in the Age Group Column. For example:

… becomes:

This athlete claimed 1.5km walk record across all age groups!


This grid achieved as follows:

  • Group the recordResults, as in the previous post by the event:
    var resultsGroupedByEvent = recordResults.GroupBy(
            p => p.Event.EventDescriptionView,
            (key, g) => new { EventId = key, Results = g.ToList()
  • Create a derived class from RecordResult called RecordResultAges that adds a string property called Ages (See next post).
    • Create a new empty list of that class:
    agesGroupedRecords = new List<RecordResultAges>();
  • For each item in the results list:
    • Get the event Id
    • Group the item’s Results by event date
    foreach (var resultGroup in resultsGroupedByEvent)
        string eventStr = resultGroup.EventId;
        // Sort
        var recordsSorted = (from r in x.Results
                    select r)
                                        .OrderBy(s => ((DateTime)s.Date).Ticks)
                                        .ThenBy(s => (s.AgeGroupView))
        // Group by date
        var results2 = recordsSorted.GroupBy(
        s => ((DateTime)s.Date).Ticks,
        (key, s) => new MultiAgeRecord
            DateId = key,
            EventId = eventStr,
            Results = (s.OrderBy(f => f.AgeGroupView)).ToList()
  • The MultiAgeRecord class is defined with properties to match the assignments in this grouping. Of interest is the read-only generation of the Ages CSV string from the Results list:
        public string Ages
                return string.Join(",", Results.Select(x => x.AgeGroupView));
  • The records in results2 are now grouped where they are same event, performance and date and have the age groups for the group as a list.
    • For each group item
    • Get the first item in group item (All items will be same except the age group).
    • Create a new RecordResultAges using that first item (the derived part) and the Ages list as a string from the group
    • Add it to agesGroupedRecords
        foreach (MultiAgeRecord multiAgeRecord in results2)
            var firstMultiAgeRecord = multiAgeRecord.Results.First();
            RecordResultAges agesRecord = new RecordResultAges(firstMultiAgeRecord, multiAgeRecord.Ages);
    } //Closing the foreach (var resultGroup ... loop


  • agesGroupedRecords is the data displayed in this grid. The second table above.
  • The background color for the rows in the grid on this page just alternates without the qualification used in page 2.

 This Category Links 
Category:Web Sites Index:Web Sites
  Next: > Club Record Certificate
<  Prev:   Club Record Certificate