
Any advice offered here very gratefully received!
Anyway, at the heart of this is a small dose of inheritance that has these two methods:
Private Function getFieldNames(_db As DBI.DBI, query As String) Dim fieldstructures As New List(Of IfieldStructure) _db.newcmd(query) For i = 0 To _db.ReaderFieldCount - 1 Dim fieldItem = New ReportStructure With {.Name = _db.ReaderGetName(i), .Width = Measurements.columnWidth(_db.ReaderGetType(i))} Dim t = Task.Factory.StartNew(Sub() fieldstructures.Add(fieldItem)) t.Wait() Next FieldCount = _db.ReaderFieldCount Return fieldstructures End Function Private Function getFieldData(_db As DBI.DBI, query As String, fields As List(Of IfieldStructure)) Dim ReportItems As New List(Of IfieldStructure) _db.newcmd(query) While _db.read With ReportItems For Each field In fields Dim reportItem As New ReportStructure With {.Name = field.Name, .Item = _db.dbin(field.Name), .Width = field.Width, .Image = ColumnIcon} Dim t = Task.Factory.StartNew(Sub() ReportItems.Add(reportItem)) t.Wait() Next End With End While Return ReportItems End Function
They work fine, I'm using the same Type to hold both the column names and the values later on.
However, the report printing is now more challenging. I'm having to use a specific printing library, in house, for this. So as I loop over the field headings I have to work out the width dynamically and in proportion. This is solved already.
The real problem is the arbitary key/value stream I end up as a result of getFieldData. Here I'm finding it harder to loop correctly. Either the values end up in a line, off the page, repeated down the page or in a single column.
I introduce fieldCount into the IReport interface and set that once I know my fieldnames. In theory I feel that knowing this should allow me to break up the "ticker" tape of values at the right point so that the print routine simply lines up the data under each heading.
So, knowing that this is likely to be recurring generic challenge, I wonder if anyone else has solved it before. Btw, I did consider dynamically generating the data type into it's own class, but then I'd need to perform Reflection on it to get the members out. Seems like overkill when i have a perfectly reasonable data stream already. It could be seen as a Dictionary, except that sometimes I need to attach an image to it.
Here's the generic print routine-it simply spits out a "printsection" which is conceptually a line. Please forgive naming kludging, refactoring comes later now

[color=blue]Private Function AddDynamicFields(items As List(Of rowElement), font As Font, color As Color) Dim psList As New List(Of PrintSection) Dim item = From r In items Select r Take Report.fieldcount For Each i In item Dim printSection As New PrintSection("HeadingText", SectionType.Dynamic, SpacingDefault.Standard) MarginWidth = 20 For Each element In returnLineElementNames() Dim headerWidth = i.width * SingleWidth printSection.addText(i.content, MarginWidth, 0, headerWidth, font, color, AlignmentEnum.Left) If IsNothing(i.image) = False Then AddRowImage(i.image, printSection) Next psList.Add(printSection) Next Return psList End Function[/color]
*For those that are interested this is a dll, the reports are "required" to be coded, not simply stored in my db (something Ive done fine before). So as I'm lazy I build a Ireport, Reportbase (Abstract) with behaviour/property that is never overridden and have reports like BirthdayReport that sets properties, including raw sql (Query) yet adds no new behaviour/properties. This way I know all reports can be treated the same by anything relying on Ireport.
From here, I simply built a list of Ireport and, for now, instantiated each one and popped it in the list. The caller receives the list, shoves it in a list box and it displays when clicked. Provision for filters is fairly easy. Note, the codebase I'm working against is legacy.
Performance wise, my only danger is instantiation runs the reports. A bit dumb, I've to seperate running from having if you like, but that doesn't matter for the next two weeks!