[Expand]General Information
[Expand]WinForms Controls
[Expand]ASP.NET Controls and MVC Extensions
[Expand]ASP.NET Bootstrap Controls
[Expand]ASP.NET Core Bootstrap Controls
[Expand]WPF Controls
[Expand]Xamarin Controls
[Expand]Windows 10 App Controls
[Expand]Office File API
[Expand]Report and Dashboard Server
[Expand]eXpressApp Framework
[Collapse]eXpress Persistent Objects
 [Expand]Product Information
 [Expand]Getting Started
 [Expand]Feature Center
 [Expand]Design-Time Features
   How to: Access Data in SQL Query Results
   How to: Bind an XPCollection to a LookUp
   How to: Bind an XPCollection to Standard Controls
   How to: Bind an XPCollection to the DataGrid
   How to: Bind an XPCollection to the Grid
   How to: Build Complex Criteria
   How to: Build Simple Criteria
   How to: Change Inheritance Mapping
   How to: Connect to a SQL Server
   How to: Connect to SQL Azure
   How to: Connect XPO to a Database Other than MS SQL or MS Access
   How to: Control Automatic Saving of Objects when Editing in a Grid
   How to: Create an Aggregated Object
   How to: Delay Property Loading
   How to: Filter By DateTime Values
   How to: Filter Persistent Objects by Type
   How to: Handle Persistent Object Initialization
   How to: Implement a Custom Criteria Language Function Operator
   How to: Implement a Full-Text Search
   How to: Implement Custom Functions and Criteria in LINQ to XPO
   How to: Implement Many-to-Many Relationships
   How to: Implement One-to-One Relationships
   How to: Link Classes Located in Different Assemblies
   How to: Make a Class or Property Non-Persistent
   How to: Make XPCollection Create Objects of Specific Type when They are Created via Bound Controls
   How to: Map to Custom Tables (Views) and Columns
   How to: Obtain a Collection of Persistent Objects by a Set of Their IDs
   How to: Obtain a Collection of Persistent Objects for Processing
   How to: Persist a BLOB Field
   How to: Prevent Changes in a Persistent Object from being Automatically Committed
   How to: Restore Deleted Objects
   How to: Use Pageable Collections
   How to: Use Read-Only Persistent Properties
   How to: Use the ContainsOperator for Objects in a Many-to-Many Relationship
   How to: Validate an Object
   How to: Work with Structures
 [Expand]Member Tables
 [Expand]API Reference
[Expand]CodeRush Classic
[Expand]Cross-Platform Core Libraries
[Expand]Tools and Utilities
 End-User Documentation
View this topic on docs.devexpress.com (Learn more)

How to: Bind an XPCollection to the Grid

The following example demonstrates how to bind a collection of Person objects to a grid control at design time and runtime. It's assumed that a grid control (the XtraGrid) has already been added to a form.

Expanded Object Structure

Let's consider a system for tracking people. Each person has a name and belongs to a specific group (Customer, Client). Information on a person is held by the Person persistent object. It provides the Name and Group properties which specify a person's name and the group to which they belong. The Group property refers to another persistent object - PersonGroup. This encapsulates a group and contains a single GroupName property.

The Person and PersonGroup persistent objects are implemented as follows:

Add this code to your project and build it before you continue.

In this example the grid control will be used to edit Person objects and these will be represented as records. The following image shows the result of this example (the Person and PersonGroup tables are populated with sample data):

Expanded Creating Collection

A grid control can work with persistent objects via the XPCollection component. This represents a collection of persistent objects of a specific type. In this example, the grid control should display Person objects, so a new XPCollection must be created and linked to the Person class.

At design time, add the XPCollection component to a form and set it's XPCollection.ObjectClassInfo property to refer to the Person class:

As a result, the collection's XPBaseCollection.DisplayableProperties property is automatically initialized with a list of public properties declared in the Person class. This list specifies which properties will be available at design time for controls that are bound to this collection:

Note that additional items are automatically included in the DisplayableProperties property:

This - represents a reference to a persistent object itself (all persistent objects have a public XPBaseObject.This property. The 'This' item represents this property.);

Oid - represents a key field of the Person object (all objects derived from the XPObject have a key field named Oid);

Group! - represents a reference to the object that is referred to by the Group property;

Group!Key - represents a key field of the object that is referred to by the Group property;

The 'This', "Group!' and 'Group!Key' fields are normally used to represent data in a lookup control. See the How to: Bind an XPCollection to a LookUp topic for for an example.

To create a collection at runtime you can do the following:

Expanded Binding Collection to Grid

Now the grid control can be bound to the created collection via the DataSource property:

After the DataSource property has been initialized the grid automatically creates columns for the fields enumerated in the collection's XPBaseCollection.DisplayableProperties list. In particular it creates columns for the Oid, Name, Group! and Group!Key fields (the captions for the 'Group!' and 'Group!Key' fields are automatically set to "Group").


The grid doesn't automatically create columns for non-browsable fields (see the System.ComponentModel.BrowsableAttribute attribute) and fields that represent collections of objects. In our example, the 'This' field is marked as non-browsable, and the 'Group' field represents a collection (in XPO any persistent property is always represented as a collection of objects in the binding mechanism). So the grid didn't create columns for these fields.

If any field in the bound data source represents a collection, the XtraGrid will represent this collection in a detail level (as a detail view). Notice the master-detail buttons in the image above.

The following code shows how to bind the grid at runtime (by default, a grid view's OptionsBehavior.AutoPopulateColumns option is set to true, so the grid automatically creates columns for the available fields in the bound datasource):

Expanded Accessing Nested Properties

To access the nested properties of persistent objects, the following syntax can be used for the DisplayableProperties property and in bound controls: 'PropertyName.NestedPropertyName'.

Let's modify the created collection's XPBaseCollection.DisplayableProperties property so that it returns a person's name and an associated group's name. To do this, set this property to the "Name;Group.GroupName" string.

Repopulate the grid's column collection. You may need to manually remove columns and reopen the project. As a result the grid only creates columns that correspond to the 'Name' and 'Group.GroupName' fields. The result is shown below:

When you run the application you should see something similar to the following (the database has been populated with a sample data beforehand):

The 'Person.Group' property is not marked as aggregated (with the AggregatedAttribute attribute). So the nested properties ('Group.GroupName') are read-only and cannot be edited. Only the 'Name' column can be edited. In XPO, changes that are made in a bound control are automatically posted to a data source on row validation.

If you need to be able to assign a group to a person by choosing a value from a list of the available group names, use the LookUp editor in a column. See the How to: Bind an XPCollection to a LookUp topic for an example.

Expanded Full code

The complete code is shown below:

Expanded See Also

Is this topic helpful?​​​​​​​