Creating and Displaying Reports using XPO

04 August 2011

Hello! I wanted to start a series describing our fabulous reporting suite by looking at it from three different angles:

  1. Data – where does the report information reside?
  2. Layout – how do we want to present the data within the report pages?
  3. Presentation – what client side technology will we be using for visualizing the reports?

The distinction between #2 and #3 is subtle yet extremely important. Our reporting suite is agnostic when it comes to #1 and #2 but very specific when it comes to #3. Laying out the report elements on the report itself should be completed (or at least prototyped) before the report is shown in any of our supported environments (WinForms, ASP.NET MVC, ASP.NET WebForms, Silverlight, WPF, and LightSwitch).

This particular installment will deal primarily with Data and Presentation. We will be looking at using an XPOCollection as the source of the data and then showing how to visualize the report in WinForms and ASP.NET.

Data

The first thing to do is create a class library project to house the XPO objects themselves.

XPO Class Project

This project has two classes that inherit from XPObject that have a many-to-many association between them. For more details on XPO we have a great Getting Started tutorial if you would like more information.

XPO Person Object

The class view above shows the type of data that I added to the Person XPO class. In addition the Category class has a Name and a Description. There is also a many-to-many between Persons and Categories.

XPO Many-to-many Association

Layout

The next thing I did was to add a new class library project to house the actual reports. Once you add a report and add a reference to our XPO library we need to instruct the report to use XPO as its data source. The easiest way to do this is to add an XPCollection to the report’s design surface:

Report XPCollection

Once this is done you will have all of the available fields in order to begin laying out the report. We will not spend too much time here. The key is to get some fields on the design surface in order to make sure the whole process is indeed working.

Presentation – WinForms

Now its time to add a third project – the WinForms viewer project. Usually I add a button to the existing form and on its click event instantiate and show the report. I thought I would try to add a little more value by showing how to create a custom report viewer form. On the main form drag a PrintBarManager onto the form’s surface:

Windows Print Bar Manager

Once this is added you should see all of the elements available in our standard report viewer dialog. Lastly we need to hook up this new report viewer to our report:

loadreport

The key element here is to set the print control’s printing system to the reports printing system. This will ensure that both items are talking about the same things when generating the report. The result:

Windows Report Viewer

If XPO is left on its own here it will (by default) create an access database to house anything you might end up saving. Now on to ASP.NET!

Presentation – ASP.NET

In ASP.NET things are a bit different. In the WinForms project XPO did a lot of the heavy lifting that it simply cannot do in ASP.NET. In this case all we have to do is tell ASP.NET where the database resides. Once we create a new ASP.NET project and add references to the data and reports assembly we add the Access database to the App_Data folder and specify the following in the Application_Startup (in the Global.asax; see docs for more details):

void Application_Start(object sender, EventArgs e)
{
    // Code that runs on application startup
    string conn = AccessConnectionProvider.GetConnectionString(
        Server.MapPath("~\\App_Data\\data.mdb"));
    XPDictionary dict = new ReflectionDictionary();

    // Initialize the XPO dictionary. 
    dict.GetDataStoreSchema(typeof(Person).Assembly);
    IDataStore store = XpoDefault.GetConnectionProvider(conn,
        AutoCreateOption.DatabaseAndSchema);
    XpoDefault.DataLayer = new ThreadSafeDataLayer(dict, store);
}

On the Default.aspx page I switch to Design mode and drop a ReportToolbar and a ReportViewer on to the design surface. If we added the references properly we should be able to select the report right on the ReportViewer’s design surface:

ReportViewer Smart Tag

We do the same thing with the ReportToolbar except in this case we are selecting the target report viewer. That should be it!

ASP.NET Report Viewer

Summary

Hope this was helpful! The main idea was that the data, the layout, and the presentation were all separate logical concepts (and in fact separate projects). If these concepts are kept separate there is nothing keeping you from swapping out data representations as well as client representations (i.e. now we want a Silverlight XPO report etc).

As always, if there are any comments and/or questions, feel free to get a hold of me!

Seth Juarez
Email: sethj@devexpress.com
Twitter: @SethJuarez

Want The Best Reporting Tool Ever?

Get The No-Compromise Reporting Tool for WinForms, ASP.NET, Silverlight and WPF! - Native integration with DevExpress WinForms and ASP.NET Controls, unequalled design-time productivity, industrial-grade features. Try a fully-functional version of DXperience for free now: http://www.devexpress.com/Downloads/NET/

Let us know what you think of our Reporting Suite by rating it in the VS Gallery!

Follow SethJuarez on Twitter

16 comment(s)
Brendon Muck [DevExpress MVP]

Glad to see Xpo used in a reporting app. I'm currently working on a system whereby the properties of an XPO object are marked with a descriptor that determines if they can be displayed on a report, and the end-user can choose which of these fields to display for an ad-hoc reporting solution.

If I may, I'd suggest that perhaps the XPView would be more suitable for reports than the XPCollection, as there is no need for an update-able data source.

4 August, 2011
Seth Juarez (DevExpress)

Well put my friend, well put.

4 August, 2011
Steve Sharkey

Seth, thanks for this - I believe I was one of those that requested this. Whilst it is understandable that most examples (for the sake of a broader audience) will use standard data access it is very nice to see XPO used specifically to see the advantages and pitfalls of combining the DX "components".

5 August, 2011
Steve Sharkey

Brendon, that sounds very interesting I haven't got to the point of offering end user configurable reporting - how do you translate a descriptor into a users ability to see/use fields? This sounds VERY useful.

5 August, 2011
Steve Sharkey

I totally agree about the XPView/XPCollection comment though I do remember some time back when I was very strict about this "rule" but found that there was some functionality (I think it was using an xpview as a data source for a lookup edit or something like that) that would not work when using an xpview but did with a collection so I have allowed that "rule" to soften (or should I say slip).

5 August, 2011
Brendon Muck [DevExpress MVP]

Steve:

I haven't quite connected all the dots yet; it's still kind of a proof-of-concept at his point, but here's how it works essentially:

1. I add a CustomAttribute (documentation.devexpress.com) to all Xpo properties that I want the user to be able to select. I call it "Queryable".

2. I have a base class called XPCustomObjectBase that inherits from XPCustomObject, and I use this as the base class for all of my Xpo classes

3. In this XPCustomObjectBase I have a method that returns a List of the properties that are deemed "Queryable".

I think I'd bind that List to a CheckedListBox or a TreeList and allow the user to select the properties they want. I'm not sure how to construct the report yet, since it would really need to be designed 100% at runtime. For now, if I can just get the result recordset to a GridControl, I'd be happy.

5 August, 2011
Hieu Nguyen~

I prefer using XPCollection over XPView, as I bind my labels to an object's parent's property without any extra code.

@Bredon: I'm thinking about that kind of customizable report for a long long time, but still no way than using an GridControl. Hope that that kind of report would be developed soon +_+

10 August, 2011
Seth Juarez (DevExpress)

I am working on some things along those lines my friends. Hopefully in a couple of months I can say more ;)

10 August, 2011
Eric Kestler

Can you please show the code in VB as well as C#, with appropriate changes/additions to any supporting images?

Thank you!

12 August, 2011
Felipe R Machado

It took me a few hours to figure out I needed to drop a XPCollection into the report designer to have design-time support for the report layout. I was going to to it manually!!!

There's one point that the ASP.NET version does "badly". It don't clear the Default Session (XpoDefault.Session), which is a dangerous thing not to do... Of course, with that cleared you'll have to find a way to "resolve" the session. I simply used the XpCollection resolve session event:

       private void MyXpCollection_ResolveSession(object sender, DevExpress.Xpo.ResolveSessionEventArgs e)

       {

           e.Session = XpoHelpder.GetNewSession();

       }

I'm using a slightly enhanced version of the XpoHelper class that is actually really thread-safe (the one provided by DevExpress fails in corner cases) and do not use a lock, but rely in lazy initialization of static nested classes to achieve this thread-safety without any performance concerns inherent of using locks... But the concept remains the same... Even if you only did new Session() it would work, as the default data layer was already created at application startup...

12 August, 2011
Jonathan Crosby 1

Great stuff.

What its still missing in XPO is: fast Excel export

XPO does a fantastic job in displaying large amounts of data in a grid, by letting the database do, what a database does best and only getting the data which is required. Now once I have a large amount of data in the grid, I have sorted it, I have filtered it....what next?? I still may need to export a large amount of data to Excel for further processing whilst keeping the nice formatting of the grid.

Please, please give this a try...use XPO to export 50'000 records to Excel. It takes far too long!

I monitored this on the database, the code for exporting using XPO can be much improved. When I pipe the same data to CSV it is superfast, but I lose all the formatting.

15 August, 2011
Brendon Muck [DevExpress MVP]

Xpo doesn't have any export capabilities.

17 August, 2011
Thomas Boring

I must be missing something.  I followed the directions in the blog post (created a new XPO Library, added two classes that inherit from XPObject, referenced that project in the DLL project I want to put my reports in) but when I drop the XPCollection from the toolbox onto the reporting surface, the "Field List" doesn't populate.

What did I miss?

16 September, 2011
Seth Juarez (DevExpress)

Make sure you compile (with F6). Then give it a retry. If not, maybe we should take this offline via email so I can get into more details. Thanks again!

19 September, 2011
Thomas Boring

No luck.  I also posted it to the forum here: community.devexpress.com/.../354699.aspx

19 September, 2011
Thomas Boring

After kicking this around in the forums, I think the problem, in my case, ended up being something wrong/odd/quirky on my machine.  I ended up uninstalling DXUniversal 111 and 10.2, cleaning out my system registry, and then re-installing.

20 September, 2011

Please login or register to post comments.