Description:
Many XPO classes in my data model reference each other. For example, a Contact class has an Address property, which is another persistent object of type Address. How can I bind visual controls to the Address property and its sub-properties?
Answer:
We've investigated the .NET Framework v.1 infrastructure and found that significant code related to data binding will only work with those data sources, which behave exactly like ADO.NET data sources (DataSet and DataTable). We had to emulate the DataSet behavior in our classes to make the data binding work with our persistent objects.
The XPCollection supports three different property descriptors for object references. The descriptor used is defined by how the property name is denoted in the data bindings. The first PropertyDescriptor name corresponds to a property name in a persistent object. The other two end with a ! and !Key accordingly. Below is a description of when to use each of the supported property descriptors.
* The descriptor with the name of a property It returns a collection of one element, which is the property's value. If the property's value is null, the returned collection is empty. The collection is needed to emulate the System.Data.DataView and thus support binding to sub-properties. If the structure were different, binding to sub-properties like ReferenceProperty.SubPropName would not work in some situations.
The implementation explained above works around the problem with property paths by allowing you to use . to access sub-properties. However, it is not suitable for a lookup editor, which needs a direct reference to an edited object. XPO provides special property descriptors for this situation.
In ASP.NET, to access sub-properties via the Eval function, use the PropertyName[0].SubProperty:
ASPx<dxdv:ASPxDataView ID="ASPxDataView1" runat="server" DataSourceID="XpoDataSourceOrders">
<ItemTemplate>
<b>Order Item:</b>:
<asp:Label ID="OrderItemLabel" runat="server" Text='<%# Eval("ItemText") %>' /><br />
<b>Customer Name</b>:
<asp:Label ID="CustomerNameLabel" runat="server" Text='<%# Eval("Customer[0].Name") %>' />
</ItemTemplate>
</dxdv:ASPxDataView>
Two-way binding via the Bind function is not supported for XPO sub-properties in ASP.NET.
* The descriptor with the name ending with ! It allows bound controls to work with the property value (a reference) directly. You should use this property descriptor to bind a lookup editor (e.g. XtraEditors LookUpEdit) which has its ValueMember property set to This.
The property descriptor with ! provides binding to lookup editors in most cases, but not all. Some Windows Forms controls cannot work with a ValueMember of type Object, e.g. a standard ComboBox binds via its Text property. As for ASP.NET, it's impossible to work with object references on the client-side (the .NET object model is not supported in scripts). The third descriptor covers this situation.
* The descriptor with the name ending with !Key It emulates the behavior of a relation column in the ADO.NET DataSet - a column storing a key value of a row in a referenced table. The descriptor represents the referenced object's key (OID). Its SetValue method finds a persistent object via the Session.GetObjectByKey function and sets it to the property.
A note about Property!Key vs. Property.Oid
You must never bind lookup editors to Property.Oid! When a new value is set to such a property, the Property's Oid is changed instead of the Property itself. Obviously, this is not the behavior you may expect when you wish to edit a Property via a lookup editor. You must bind to Property!Key instead. In this case, XPO will find an object by its key and correctly change the reference. As explained below, you can also use Property! to bind to a lookup editor - internally it works differently than Property!Key, but produces the same result.
A note about which descriptor you should use for your lookup editors - the one ending with ! or ending with !Key
ASP.NET applications must use the descriptor with !Key. As for Windows Forms applications, you can use any of the ! and !Key descriptors. However, please remember that an object referenced by the !Key descriptor can find only those properties, which are saved in the database. While an object is not saved, it cannot be found by the GetObjectByKey method.
See Also:
How to adjust the LookUpEdit so it can be used with persistent objects
How to use XPO in an ASP.NET (Web) application
How to display a complex property's subproperties in data bound controls
How to Bind an XPCollection to a LookUp