Back to main post (including source): http://blogs.vbcity.com/hotdog/archive/2006/10/26/6568.aspx
How the control came to be
(this is just the thoughts of the last couple of days written down and most likely will only ever read by people who are bored ;-) )
Everyone who worked with Access generally misses at least 2 things when working in other environments: the report engines and continuous forms (or subforms). Although when intensively used, Access may have exposed many flaws, those are 2 items that made up for a lot of them.
In .net you can easily enough use docking to create a list of controls, but when giving them the proper position, you have to use the Z order which is not the fastest solution. And yes, there are the master detail solutions, but let's be honest, they often just aren't the way you want to represent your data.
There were 3 major points for the creation of the continuous control:
1. it had to be usable with the default .net BindingSource component (through the bindingsource any datasource can be used)
2. it had to be fast with large lists, which meant that the representation only had to be created when either the record was selected or if the record was inside the viewable area.
3. it had to be usable by simply dropping controls on it in designtime, so that the user is not obliged to create a custom control for each subform
In my view, if the points above could be accomplished, the combination of the .net databinding and all the other .net functionality would definately make the wanting of other types of subforms a thing of the past. (Only the report engine is still something. Anyone interested in starting that project? :-D )
Although I did find some other continuous form projects on the web, they just didn't suit my needs (as I'm sure this control will not suit many of your needs :p )
At first I was trying to add controls for the entire viewable area. That meant that multiple copies of the original controls were used. Now that gave problems with point 3: it was easily doable for predefined controls, using a single controltype, but for design time drag and drop functionality, that would mean copying the original controls. To do that, the only way seemed to be using reflection to copy all fields and properties. That in turn gave the risk of shallow copies. All in all: reflection was too dangerous on itself.
Then came using the CodeDomSerializer to catch that part of the designer that created the code that created the first control instances. That seemed to be promising, but gave all sorts of other headaches. It is still an avenue I'd like to finish some day.
But still, since only one control can be focused at a time, I found it a bit of waste to create multiple complex controls of the same type.
Then suddenly a vague mist disappeared and the sounds weren't so muffled anymore. From within those mists a voice spoke: “Remember, remember“. Although I like the Lion king, I was wondering why a subconcious voice would start quoting from that film when dealing with coding. But then a memory did come: where the previous .net versions didn't have that possibility, .net 2.0 had the ability to paint the graphical representation of a control to a bitmap.
Effectively that meant, that if the information had to be shown to the user, the bindingsource's position had to be changed temporarily to update the control, paint that information to a bitmap, and show the image when needed. When clicked on it, the position would be set the index it represented and the actual detail information control(s) would be focused.
In the end, that was a lot easier than expected. (bigger problems occured in getting the designer to do as wanted) and the link to the source code represents the result.
All in all it still has a couple of disadvantages:
1. It must be bound to a bindingsource
2. All editable controls must be databound to show different information per record
Now imho these aren't really disadvantages, since they fit exactly in the scenario for which the control was created, but it can complicate some uses.
The first 'problem' is the smallest: a datasource can be almost any type. you can quickly asign an array or a (generic) list. even if you just asign an arraylist, you can display the 'subform' as many times as fit in the list. And of course all other normal data sources can be used as well. If you tend to use a particular datasource often, I'd suggest adding a property that automatically creates the encapsulating bindingsource for that collection.
About the second issue: if you add an unbound label, the label will display the same text for each record. Since it's a label, that's probably exactly what it's supposed to do. But if you add an unbound textbox, the state of that textbox will not be remembered per record. Rather whatever you enter will be taken with it to the next record you focus. Of course that's logical, because there's no underlying data for the textbox if it's unbound and so there is only one instance of the text it represents. So you'll need to bind it to the source, but again: that's exactly what a subform is supposed to do ;-)
One other small issue that might occur: some controls don't fully support the drawtobitmap functionality. An example of such a control is the richtextbox. But since these types of controls normally won't be used for data editing, that most likely won't be a problem either.