So, at last I've got a chance to use Inka in a real project. Nothing complicated, but it revealed something new to me.
Here's the idea. When somebody requests a calendar, you create an object of type CalendarOrder, which is, basically, a CalendarType and a Quantity. CalendarType has a list of, well, whatsisname's: materials and work. I call it XPenceType. So, a Trio calendar, for example, may require 1 spiegel, 0.2 m of spring etc. plus stamping, shpongling, and shpookling. Each item has a certain price. The goal is to display the price of materials, one by one and the sum of these, and the same for work, plus the sum of these two.
Naturally, I wanted to test-drive it. But I'll save testability for another post.
As I didn't want to get too smart, I created a new OrderReport class and put the whole initialization mess in the constructor (not very smart of me, I know). I add a group section called outerSection and add a separate method to set its data. In my test, I retrieve a reference to this section by its ID and verify that it should have two details. Why two? First is for materials, second is for work.
My first idea was to use
Dim data = From type In Model.XPenceType.FindAll() _
Group type By type.IsMaterial Into Group
Which failed:
Inka.DesignByContract.PreconditionException: The data item System.Boolean should contain the property Key
The reason is that a grouping section expects IEnumerable(Of IGrouping) as data source. The Group By statement, on the other hand, does not always produce this.
Indeed, it turned out that while C# compiles LINQ statements into an IEnumerable<IGrouping<...>>, VB compiles them to IEnumerable(Of anonymous type), where the anon type contains both the key and the details. So, while you can use LINQ in C# for our purpose, you can't do that in VB. Instead, you should use an extension method, like this:
Dim data = Model.XPenceType.FindAll().GroupBy(Of Boolean) _
(Function(type) type.IsMaterial)
At this point I have two groups, one for materials and the other for work types. The group section is something similar to a group header (or footer) in Access and the like. It uses the Key property of the data source for the DataItem property. The Key is exactly the stuffy we group by. In our case, it is a boolean property IsMaterial. At this point, we are capable of displaying something like true/false in the group section. What I really need is show Material/Work. So, I need a custom element.
A really smart way of defining this element would be to derive from LabelElement and implement IDataElement. However, I, as I said, didn't want to be too smart, so I just derived it from DataElement (thus inheriting a lot of unneeded functionality, but also saving myself a few keystrokes). I added two properties, TrueValue and FalseValue, and overrode the GetValue method, which is the standard way of defining new text elements.
Protected Overrides Function GetValue() As String
Dim value As Boolean = Me.DataObject
Return If(value, Me.TrueValue, Me.FalseValue)
End Function
(to be continued)