Skip to main content

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.

Create a Report and Bind It to a Non-Persistent Data Type

  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, VisibleInReports]
    public class MyNonPersistentObject : NonPersistentBaseObject {
        public string Name { get; set; }
    }
    
  2. Create a report for the MyNonPersistentObject data type. You can add a predefined static report in Visual Studio or create a report at runtime.

    Blazor - Specify Object Type

    Important

    Non-persistent objects do not support the ViewDataSource component – use CollectionDataSource to bind a report to data.

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

    Blazor - Empty Report

Supply the Report with Data (Initialize Non-Persistent Objects)

Use the Application Builder

In the Application Builder code, handle the NonPersistentObjectSpace.ObjectsGetting event as shown below:

File: MySolution.Blazor.Server\Startup.cs, MySolution.Win\Startup.cs

using System.ComponentModel;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Core;
// ...
// Handle the `NonPersistentObjectSpace.ObjectsGetting` event.
builder.ObjectSpaceProviders.Events.OnObjectSpaceCreated = context => {
    if (context.ObjectSpace is NonPersistentObjectSpace nonPersistentObjectSpace) {
        nonPersistentObjectSpace.ObjectsGetting += NonPersistentObjectSpace_ObjectsGetting; 
    }
};
// ...
private static void NonPersistentObjectSpace_ObjectsGetting(object sender, ObjectsGettingEventArgs e) {
    // In the event handler, populate the `e.Objects` collection 
    // with non-persistent objects of the required type.
    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;
    }
}
// ...

Implement an IObjectSpaceCustomizer

  1. In the module project, implement the IObjectSpaceCustomizer service as shown below:

    File: MySolution.Module\NonPersistentObjectSpaceCustomizer.cs

    using System.ComponentModel;
    using DevExpress.ExpressApp;
    using DevExpress.ExpressApp.Core;
    
    public class NonPersistentObjectSpaceCustomizer : IObjectSpaceCustomizer {
        private readonly IObjectSpaceProviderService objectSpaceProvider;
        private readonly IObjectSpaceCustomizerService objectSpaceCustomizerService;
    
        public NonPersistentObjectSpaceCustomizer(
        IObjectSpaceProviderService objectSpaceProvider, 
        IObjectSpaceCustomizerService objectSpaceCustomizerService) {
            this.objectSpaceProvider = objectSpaceProvider;
            this.objectSpaceCustomizerService = objectSpaceCustomizerService;
        }
    
        public void OnObjectSpaceCreated(IObjectSpace objectSpace) {
            if(objectSpace is NonPersistentObjectSpace nonPersistentObjectSpace) {
                // Handle the `NonPersistentObjectSpace.ObjectsGetting` event.
                nonPersistentObjectSpace.ObjectsGetting += NonPersistentObjectSpace_ObjectsGetting;
                nonPersistentObjectSpace.ObjectByKeyGetting += NonPersistentObjectSpace_ObjectByKeyGetting;
                nonPersistentObjectSpace.Committing += NonPersistentObjectSpace_Committing;
                nonPersistentObjectSpace.PopulateAdditionalObjectSpaces(objectSpaceProvider, objectSpaceCustomizerService);
            }
        }
    
        private void NonPersistentObjectSpace_ObjectsGetting(object? sender, ObjectsGettingEventArgs e) {
            // In the event handler, populate the `e.Objects` collection 
            // with non-persistent objects of the required type.
            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;
            }
        }
        private void NonPersistentObjectSpace_ObjectByKeyGetting(object? sender, ObjectByKeyGettingEventArgs e) {
            //...
        }
        private void NonPersistentObjectSpace_Committing(object? sender, CancelEventArgs e) {
            //...
        }
    }
    
  2. Register your IObjectSpaceCustomizer service implementation in the Starup.cs file of the Blazor and WinForms applications. Use the TryAddEnumerable method to register these services:

    File: MySolution.Blazor.Server\Startup.cs, MySolution.Win\Startup.cs

    public void ConfigureServices(IServiceCollection services) {
        //...
        services.TryAddEnumerable(ServiceDescriptor.Scoped<IObjectSpaceCustomizer, 
            NonPersistentObjectSpaceCustomizer>());
        //...
    }
    

The following image demonstrates the result:

Blazor - Result