Skip to main content
.NET 6.0+

XPCollection Class

The collection of persistent objects that implements delayed loading and can serve as a data source for a data-aware control.

Namespace: DevExpress.Xpo

Assembly: DevExpress.Xpo.v24.1.dll

NuGet Package: DevExpress.Xpo

#Declaration

public class XPCollection :
    XPBaseCollection

#Remarks

The XPCollection class represents a collection of persistent objects. When creating a collection, you need to specify the type of objects that will be stored in the collection (at runtime - by specifying the object’s type in the class’s constructor and at design time - via the XPCollection.ObjectClassInfo property).

In most cases, a collection needs to be created to access objects of a specific type from a data store. The XPCollection class implements delayed loading, i.e., it’s populated with persistent objects from the data store on demand.

For instance, you can create an XPCollection instance, that is marked to contain custom Person objects. The collection, however, will be populated with Person objects from a data store only when the collection’s contents is accessed. Consider the following example:

using DevExpress.Xpo;
using DevExpress.Data.Filtering;

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

   public bool IsMale {
       get { return fIsMale; }
       set { SetPropertyValue(nameof(IsMale), ref fIsMale, value); }
   }
   bool fIsMale;

}

// Create a collection that will retrieve Person objects whose IsMale field is set to false.
XPCollection xpCollectionPerson = new XPCollection(typeof(Person),
CriteriaOperator.Parse("IsMale==false"));
// The collection is not yet populated with objects from a data store.
// ...
// Read the number of objects in the collection.
// At this point, the collection will be populated with data. 
int ctr = xpCollectionPerson.Count;
// ...

Note

When designing ASP.NET WebForms applications, use the XpoDataSource component, rather than the XPCollection.

#Creating an XPCollection

In terms of XPO, the XPCollection represents a collection object which can be used to retrieve collections of persistent objects from a data store and bind them to UI controls.

You can create a collection in any of the following ways:

  • Create an XPCollection programmatically.
  • Create a collection at design time. This option creates an XPCollection object on your form or component whose properties you configure manually.

To create an empty XPCollection, set the XPBaseCollection.LoadingEnabled property to false.

#Creating an XPCollection at Runtime

To retrieve all the objects of a particular type, pass the required object type and the Session object (if you don’t use the default session) as the constructor’s parameters as shown in the following code example.

// Retrieves all the Person objects (including descendants) using the default session.
XPCollection collection = new XPCollection(typeof(Person));

Note

To retrieve persistent objects using a custom Session, you also need to pass the session object to the collection’s constructor.

To customize the order of the contents and reduce the set of objects in the resulting collection object, you need to specify additional search, filter, or sorting criteria. See Query a Data Store and Creating Criteria for more information about creating and handling collections in code.

#Creating an XPCollection at Design Time

To create the XPCollection object at design time, follow the steps below.

  1. From the DX.24.1: ORM Components tab of the Toolbox, drag an XPCollection object onto your form or component.
  2. Select XPCollection in the designer and then use the Properties window to set the session used to retrieve a collection in the corresponding property. You can select the session object from the list of sessions defined in your form or component. When the XPCollection is initialized, the Session property is pre-initialized with the default session (see Session.DefaultSession for details).
  3. To define the type of persistent object to be retrieved by the collection, set the ObjectClassInfo property. You can select the object from a list of the persistent objects defined in your form or component. Session property modification resets the ObjectClassInfo property.

    Note

    By default, assemblies from project references are not loaded into the current application domain by Visual Studio. As a result, types declared in external assemblies are not added to the ObjectClassInfo combo box in the designer. To trigger loading types from a specific assembly, access any of these types in the form/component initialization code. An example is provided in the XPCollection.ObjectClassInfo topic.

  4. If you want to specify the list of properties to be displayed in a bound control, set the DisplayableProperties property. It includes all object properties by default.
  5. You can set the DisplayableProperties property as a single unit. The list is comprised of property names separated by semicolons. The list of properties is recreated every time the ObjectClassInfo property is changed.
  6. To set collection binding behavior in the bound UI control, set the corresponding property by selecting the options from the check list. The options selected are displayed in the BindingBehavior property as a string with option values separated by commas. The default property value is AllowNew, AllowRemove. See the definition of the XPBaseCollection.BindingBehavior for a list of available option values.
  7. By default, the XPCollection does not include deleted objects. To override this behavior, you can set the SelectDeleted property to true.
  8. You can specify the sort order of collection contents via the SortProperty collection which is accessible via the Sorting property. In the SortProperty Collection Editor you can specify the properties which control the sort order and sort order direction for each property.

    Note

    If collection options need to be set at runtime, you can configure collection object properties as dynamic properties. For more information, see Configuring Applications Using Dynamic Properties in the MSDN library.

  9. By default, the XPCollection retrieves all the objects which match the search criteria. To override this behavior, you can set the value of the TopReturnedObjects property to specify the maximum number of objects retrieved.
  10. If you want to rename the collection object, set its Name property.
  11. If you want to change the visibility level of the collection object, set its Modifiers property.
  12. You may also designate methods to handle collection-specific events on the Events tab in a way you typically do for the other objects.

You can now select the collection as a DataSource in a bound UI control, for example the standard DataGrid (see How to Bind an XPCollection and How to Bind an XPCollection to the LookUp for details).

#Binding an XPCollection to a Control

XPCollection implements the IBindingList and ITypedList interfaces, so it can serve as a data source for a visual data-aware control. For instance, when a collection is bound to a grid control (for instance, the XtraGrid), the collection’s objects would be represented as editable records in the grid and object properties would be represented by grid columns (see the image below).

MemberDTimeVisibility

In this instance, the XPBaseCollection.BindingBehavior property allows you to specify whether adding new items to and/or removing existing items from the collection is allowed by the grid. The XPBaseCollection.DisplayableProperties provides a list of the object properties that are available for binding at design time.

Note

The XPCollection‘s implementation of the ITypedList interface limits the number of nesting levels in the object’s hierarchy to four levels at design time. This is done on purpose, because in some situations, Visual Studio attempts to retrieve the full hierarchy. This leads to Visual Studio hanging if the business model has self-referencing associations.

At runtime, there is no limitation for the nesting level, and you can bind controls to any property at runtime, even if it isn’t visible in the designer. Also, the end-user designer doesn’t inherit this problem, and the entire hierarchy will be retrieved.

#Filtering an XPCollection

The XPCollection can be filtered when retrieving objects from a data store. To filter objects on the data store side, use the XPBaseCollection.Criteria property. Alternatively, to filter objects on the client side, use the XPBaseCollection.Filter property. For detailed information, see Filtering.

#Concepts

#Member Table

#Task-Based Help

#Example

The following example demonstrates how to implement a one-to-many relationship between persistent objects, so that child objects are considered a part of their owner (when an owner is deleted, its aggregated objects will be automatically deleted; similarly, when an object is saved its aggregated objects will also be saved).

A one-to-many relationship is set up using the AssociationAttribute attribute. The AggregatedAttribute attribute is used to implement aggregation.

In this example, a Person object can have multiple addresses that are stored in the Person.Addresses collection. Each address in this collection is represented by an Address persistent class. The Person.Addresses property is marked with the AssociationAttribute and AggregatedAttribute attributes.

If you run the code below as is, the console output will be:

7654 Amsterdam Ave, New York, NY 555 Harbor Way, Santa Barbara, CA

If you remove the Aggregated attribute, the output will change to:

7654 Amsterdam Ave, New York, NY 7654 Amsterdam Ave, New York, NY

using System;
using System.Collections.Generic;
using System.Linq;
using DevExpress.Xpo;

namespace ConsoleApplication1 {
    public class Person : XPObject {
        public string Name {
            get { return fName; }
            set { SetPropertyValue(nameof(Name), ref fName, value); }
        }
        string fName;

        [Association("PersonAddresses"), Aggregated]
        public XPCollection<Address> Addresses {
            get { return GetCollection<Address>(nameof(Addresses)); }
        }
    }

    public class Address : XPObject {
        [Association("PersonAddresses")]
        public Person Owner {
            get { return fOwner; }
            set { SetPropertyValue(nameof(Owner), ref fOwner, value); }
        }
        Person fOwner;

        public string AddressInfo {
            get { return fAddressInfo; }
            set { SetPropertyValue(nameof(AddressInfo), ref fAddressInfo, value); }
        }
        string fAddressInfo;

    }

    class Program {
        static void Main(string[] args) {
            // Create a new instance of the Person class
            Person person = new Person() { Name = "Andrew Smith" };
            // Add an address for the person.
            Address address = new Address() { AddressInfo = "7654 Amsterdam Ave, New York, NY" };
            person.Addresses.Add(address);

            // Save the created Person object. The contents of the Addresses collection will be saved as well.
            person.Save();
            // Reload the object to verify if changes were saved.
            address.Reload();
            Console.WriteLine(address.AddressInfo);

            address.AddressInfo = "555 Harbor Way, Santa Barbara, CA";
            person.Save();
            // Reload the object to verify if changes were saved.
            address.Reload();
            Console.WriteLine(address.AddressInfo);

            Console.ReadKey();
        }
    }
}

#Implements

See Also