How to: Display Non-Persistent Objects in a Report

  • 3 minutes to read

This topic describes how to create a report based on non-persistent data. Use this approach to analyze and report data obtained from runtime calculations, stored procedures, arbitrary SQL queries, or third-party services.

  1. Declare a non-persistent class (for example, MyNonPersistentObject), and decorate it with the DomainComponent and VisibleInReports attributes.

    using DevExpress.ExpressApp.DC;
    using DevExpress.Persistent.Base;
    // ...
    [DomainComponent, VisibleInReportsAttribute]
    public class MyNonPersistentObject {
        public string Name { get; set; }
    }
    
    NOTE

    The INotifyPropertyChanged, IXafEntityObject and IObjectSpaceLink interface implementations were omitted in this example. However, it is recommended to support these interfaces in real-world applications (see PropertyChanged Event in Business Classes and Non-Persistent Objects).

  2. Create a predefined static report in Visual Studio or create a report at runtime with the MyNonPersistentObject data type.

    In Visual Studio, set the DataSourceBase.ObjectTypeName property of the CollectionDataSource component to MyNonPersistentObject.

    At runtime, choose MyNonPersistentObject in the Report Wizard's Data Type combo box.

    IMPORTANT

    Non-persistent objects do not support ViewDataSource - use only CollectionDataSource.

    At this step, the created report displays no data in the preview.

  3. Open the WinApplication.cs (WinApplication.vb), WebApplication.cs (WebApplication.vb) and/or MobileApplication.cs (MobileApplication.vb) code. Ensure that the NonPersistentObjectSpaceProvider is registered in the overridden CreateDefaultObjectSpaceProvider method (in addition to the existing XPObjectSpaceProvider or EFObjectSpaceProvider). The Solution Wizard automatically adds this code but it can be missing if you used an older XAF version to create your project.

    protected override void CreateDefaultObjectSpaceProvider(CreateCustomObjectSpaceProviderEventArgs args) {
        // ...
        args.ObjectSpaceProviders.Add(new NonPersistentObjectSpaceProvider(TypesInfo, null));
    }
    
  4. Subscribe to the XafApplication.ObjectSpaceCreated event, and subscribe to the NonPersistentObjectSpace.ObjectsGetting event in its handler. In the ObjectsGetting handler, check if the requested object type is MyNonPersistentObject type and populate the e.Objects collection.

    using System;
    using System.ComponentModel;
    using DevExpress.ExpressApp;
    // ...
    public sealed partial class MyModule : ModuleBase {
        //...
        public override void Setup(XafApplication application) {
            base.Setup(application);
            application.SetupComplete += Application_SetupComplete;
        }
        private void Application_SetupComplete(object sender, EventArgs e) {
            Application.ObjectSpaceCreated += Application_ObjectSpaceCreated;
        }
        private void Application_ObjectSpaceCreated(object sender, ObjectSpaceCreatedEventArgs e) {
            var nonPersistentObjectSpace = e.ObjectSpace as NonPersistentObjectSpace;
            if(nonPersistentObjectSpace != null) {
                nonPersistentObjectSpace.ObjectsGetting += ObjectSpace_ObjectsGetting;
            }
        }
        private void ObjectSpace_ObjectsGetting(Object sender, ObjectsGettingEventArgs e) {
            if (e.ObjectType == typeof(MyNonPersistentObject)) {
                BindingList<MyNonPersistentObject> objects = new BindingList<MyNonPersistentObject>();
                for (int i = 1; i < 10; i++) {
                    objects.Add(new MyNonPersistentObject() { Name = string.Format("Object {0}", i) });
                }
                e.Objects = objects;
            }
        }
    }
    

The following image demonstrates the result.