|
|
Thursday, May 17, 2007 Data binding simplification Milos controls support native data binding. It has been like that since the beginning of (Milos-) time. So for instance, if you want to bind a textbox to a property on a business entity, you can simply set up the binding by specifying the name of the entity and property you want to bind to, using the ControlSource property of the textbox.
This is pretty straightforward, but there is one somewhat tricky part to this: The member the control binds to is specified from the control's point of view. So for instance, to bind a textbox on a form to a business entity's "LastName" property (assuming the business entity is a member of the same form as is the case with the default Milos data entry forms), the ControlSource has to be set to "this.Parent.MyEntity.LastName". Or, one can also use the VB version: "Me.Parent.MyEntity.LastName". Both these versions are interchangeably and work regardless of the language you use. In fact, the "this/Me" part is completely optional. You could as well set the ControlSource to this: "Parent.MyEntity.LastName".
So far, so good. The tricky part is that if the textbox is inside another container, the hierarchy changes. For instance, if the textbox exists inside a tab page inside a tab control, the ControlSource needs to be set to this: "this.Parent.Parent.Parent.MyEntity.LastName". That is because the textbox exists inside the tab page (Parent), which exists inside a tab control (Parent.Parent), which exists inside the form (Parent.Parent.Parent), which has the entity (Parent.Parent.Parent.MyEntity).
It is perfectly logical, but it is also a common source of frustration, since it is a) easy to get the exact number of parent references wrong, and b) when the control moves into a different container, the path changes. We have now added a simplification to the expressions used by the ControlSource property. The approach described above is still perfectly valid, but the whole "parent" chain is now optional. So the ControlSource can now be set to "MyEntity.LastName", regardless of where the textbox (or any other control with a ControlSource property) lives.
The way this works is that Milos auto-discovers the hierarchy. It starts out with the current control. If it has a "MyEntity" member, then that is used for binding. If not, Milos goes to the parent control and looks for it there. It then continues up the chain until there is no parent anymore (typically at the window level). If no member of the specified name is found, a null reference exception is thrown.
So this is nice, because it simplifies things a lot. There are two downsides though: 1) This discovery is done at runtime and thus introduces runtime overhead. It is pretty fast, but if you have a form with hundreds of controls, you should probably consider specifying the full path (at least that is an optimization option in case you run into form startup performance issues). 2) The expression may be ambiguous. If you want to bind to the MainEntity on the form, but there happens to be another object in the chain that has a member of the same name, you may accidently bind to the wrong object. In those cases, one also has to specify the full path.
Some people say it is a bit odd to just bind to "MyEntity.LastName", because one cannot tell where MyEntity lives. To make things a bit clearer, you can use other pointers, such as "thisform", "class", or "container". They all mean the same exact thing, which is "diddly-squat". In other words: These keywords are ignored completely. But some think it is more readable to set the control source to "thisform.MyEntity.LastName", "Container.MyEntity.LastName", or "class.MyEntity.LastName". So go ahead and use these keywords if you feel they make things clearer. Be aware that they do not actually do anything. "thisform" for instance does not necessarily reference a form. It can also be used in panes for instance. It also does not solve the ambiguity problem, as the auto-discovery mechanism may still pick up "in between" object references from the hierarchical chain. (What do you think about this actually? I'd be interested in feedback on this...).
Anyway: Hopefully, this will simplify the task of specifying the control source expression.
Note: This feature has been implemented and has undergone almost complete testing, so it will most likely show up in the next Milos build...
Posted @ 11:48 AM by Egger, Markus (markus@code-magazine.com)
|