Skip to main content
.NET Framework 4.6.2+

How to: Bind an XPCollection to the Grid

  • 7 minutes to read

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.

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:

public class Person : XPObject {
   public Person() {
      Name = "";
      Group = null;
   }
   public string Name {
       get { return fName; }
       set { SetPropertyValue(nameof(Name), ref fName, value); }
   }
   string fName;

   public PersonGroup Group {
       get { return fGroup; }
       set { SetPropertyValue(nameof(Group), ref fGroup, value); }
   }
   PersonGroup fGroup;

}

public class PersonGroup : XPObject {
   public PersonGroup() {
      GroupName = "";
   }
   public string GroupName {
       get { return fGroupName; }
       set { SetPropertyValue(nameof(GroupName), ref fGroupName, value); }
   }
   string fGroupName;

}

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):

Ex_BindingToGrid_RunGrid

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:

Ex_BindingToGrid_SetObjectClassInfo

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:

Ex_BindingToGrid_DisplayableProp_Default

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:

XPCollection xpCollectionPerson = new XPCollection(typeof(Person));

Binding Collection to Grid

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

Ex_BindingToGrid_SetDataSource

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”).

Ex_BindingToGrid_GridPopulateColumns1

Note

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):

gridControl1.DataSource = xpCollectionPerson;

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.

Ex_BindingToGrid_DisplayableProp_New

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:

Ex_BindingToGrid_GridPopulateColumns2

xpCollectionPerson.DisplayableProperties = "Name;Group.GroupName";
gridControl1.MainView.PopulateColumns();

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

Ex_BindingToGrid_RunGrid

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.

Full code

The complete code is shown below:

using DevExpress.Xpo;

public class Person : XPObject {
   public Person() {
      Name = "";
      Group = null;
   }
   public string Name {
       get { return fName; }
       set { SetPropertyValue(nameof(Name), ref fName, value); }
   }
   string fName;

   public PersonGroup Group {
       get { return fGroup; }
       set { SetPropertyValue(nameof(Group), ref fGroup, value); }
   }
   PersonGroup fGroup;

}

public class PersonGroup : XPObject {
   public PersonGroup() {
      GroupName = "";
   }
   public string GroupName {
       get { return fGroupName; }
       set { SetPropertyValue(nameof(GroupName), ref fGroupName, value); }
   }
   string fGroupName;

}

// ...

XPCollection xpCollectionPerson = new XPCollection(typeof(Person));
xpCollectionPerson.DisplayableProperties = "Name;Group.GroupName";
gridControl1.DataSource = xpCollectionPerson;
See Also