Comboxes in Eco II
The winforms ComboBox is a powerful and versitile component. Since ECO supports .Net databinding it is usually fairly straightforward to use. In one particulary common case however, it turns out there are one or two pitfalls along the way.
So, we will now use a ComboBox to set an association, in this case which department a particular person works for,
The model
The model is as simple as possible, only two classes and an association. The only additional thing done is to set the Default String Representation of the Department class to ‘Name’ so that it will display nicely in the UI.
A small project using this model can be found here. The form has a grid showing all persons connected the the ExpressionHandle ehAllPersons, and a detail panel with a TextBox connected to ehAllPersons - Name. In anticipation of the future it also has an (unused) ExpressionHandle ehAllDepartments with the expression Department.allInstaces, and some real estate reserved for a control for displaying and selecting the departement.
Adding a combox - surprise
The next thing to do is obviously to add a ComboBox to the form, and connect its DataSource property to ehAppDepartments. But when do this and run the application we are in for a surprise:
What does this mean? Well, by default the ComboBox will call ToString() on the objects in the list to get a string to display. And the objects it this case are of an internal type used by the handles for connecting the Eco objects to the .Net databinding architecture. Each of these objects will in turn have members. In this case they will all have the single member Name, containing the name of the Department. So, correcting the display is a simple matter of setting the DisplayMember property of the ComboBox to Name.
However, this draws our attention to another problem. If we try to databind to the SelectedItem property of the ComboBox we will get a Borland.Eco.Handles.RenderedTuple. That is not what we want. We want the Department object that the row represents.
Fortunately the Combobox offers another alternative. Instead of binding to the object, we can set the ValueMember to the name of one of the columns on ehAllDepartments and databind to SelectedValue rather than SelectedItem
So we need another member to ehAllDepartments, with a value is the Department object itself. We get it by adding a column to the Columns property, naming it MySelf and giving it the OCL expression self.
BTW, In case you hadn’t noticed the .Net documentation is really confusing when referring to the individual values in the "Rows" of databound lists. In some places they are called Properties, in others Members (such as ValueMember on the Combobox) and in yet others Columns. The Eco handles continue this tradition of confusion, by having the property AddDefaultProperties, but calling the collection defining additional ones Colums.
The same but different
Now there is only one remaining problem, and that is what to bind to SelectedValue. At first sight it seems that we can use the autogenerated Department column. However, it is primarily intended for displaying the link in a grid, so it is string-valued and has the OCL expression Department.AsString. Again we need another member, and this time we need one that represents the assocciation end itself, rather than the default string representation of the object at the other end.
The solution is similar; we add a column DepartmentObject to ehAllPersons with the OCL expression self.Department, and then bind the SelectedValue property of the ComboBox to ehAllPersons - DepartmentObject.
The complete set of databinding properties on the Combobox is:
Immediate action
Now the application works. But still we are not quite happy. The value selected in the ComboBox is applied to the object when focus leaves the ComboBox . This is the standard behavior for databound components, but we would like to see some more action here, so that the new value is applied as soon as the selection is changed. This can be accomplished by adding the following code to the SelectedIndexChanged event of the Combox:
procedure TWinForm.cbDepartment_SelectedIndexChanged(sender: System.Object; e: System.EventArgs);
var
Cm: CurrencyManager;
begin
Cm := CurrencyManager(BindingContext[ehAllPersons]);
if Assigned(Cm) then
Cm.EndCurrentEdit;
end;
The finished project can be found here
Summary
In order to use a combobox to set a single association end we need to do several things.
- Add a column with the expression self to the handle holding the list of values
- Add a column representing the associaton end to be set to the handle holding the object to be edited
- Set DataSource, DisplayMember, ValueMember and Databinding - SelectedValue on the Combobx
- (Optionally) implement SelectedIndexChanged in the Combobox.
They are more or less obvious once you know them, but not all that easy to get right the first time.
Share This | Email this page to a friend
Posted by Jan Nord?n archive on December 17th, 2004 under ECO II | 5 Comments »Who am I
My name is Jan Nordén, and I am the architect for ECO, a model driven framework for .NET that ships with Delphi.
This blog will cover all things ECO.
Share This | Email this page to a friend
Posted by Jan Nord?n archive on October 19th, 2004 under Uncategorized | 1 Comment »

RSS Feed
