Category Archives: Developer Express

Emitting XtraScheduler Resource ID XML


I’ve recently been spending a bit of time directly accessing and manipulating the data that the DevExpress XtraScheduler emits when persisting its changes. You can read a bit about the structure of the data tables here and view the MSSQL schema here.

Most of the columns are relatively straight-forward, containing either strings or ordinal representations of enum values. However, the resource ID, reminder info, and recurrence info columns all contain specifically formatted XML strings. Luckily the DevExpress.XtraScheduler.XML namespace contains several helpful classes to assist in reading and writing these values.

In a previous blog post I discussed reading the resource ID’s stored by the VCL ExpressScheduler, returning them as a comma-delimited string. Given such a string called resources, in order to emit the proper XML you could do the following:

                string[] resourceArray = resources.Split(',');

                ResourceIdCollection idCollection = new ResourceIdCollection();
                foreach (string resourceID in resourceArray)
                {
                    idCollection.Add(int.Parse(resourceID));
                }

                AppointmentResourceIdCollectionContextElement element = new AppointmentResourceIdCollectionContextElement(idCollection);
                string xmlString = element.ValueToString();

With these few lines of code we have the necessary XML to access and store within the DB:

<ResourceIds>
  <ResourceId Type="System.Int32" Value="1"/>
  <ResourceId Type="System.Int32" Value="4"/>
</ResourceIds>

In a future post I’ll discuss emitting the XML representations of reminder and recurrence info as well.

UPDATE: There’s a real-world example of this technique you can find here. It is an open source project for transferring data from ExpressScheduler to XtraScheduler.

Accessing ExpressScheduler Resource Information from .NET

In a previous blog post I discussed how to access the recurrence information that the VCL ExpressScheduler stores in its DB from a .NET application. Reading and writing the recurrence information is possible from .NET given a knowledge of the struct layout that the Delphi control uses.

However, if you want to read the resource information that ExpressScheduler stores in its DB from .NET, this requires using a Delphi DLL. This is because the Delphi scheduler control stores the resource ID’s for appointments in a single field but in multiple formats depending on the appointment. For instance, if the appointment has only one associated resource, its resource ID will be stored as a Delphi variant. However, the value will be stored as a Delphi variant array of variants if the appointment is associated with multiple resources.

Luckily, both Delphi and .NET make it straight-forward to interoperate between them and DevExpress has a simple utility method we can use to simplify things as well.

Start off with a new Delphi DLL project by clicking File>New>Other in Delphi XE2. On the New Items dialob, select Delphi Projects followed by Dynamic-link Library.


Start by adding both Variants and cxSchedulerStorage to the uses clause of the DPR. Then, add the following exported method to the DPR:

procedure ResourceIDBlobToString(const AResourceID: PByteArray; out AResult: PByteArray); export; stdcall;

var
  ResourceIDVar: Variant;
begin
  ResourceIDVar := cxFieldValueToVariant(AnsiString(AResourceID));
  if VarIsArray(ResourceIDVar) then
    AResult := PByteArray(VarArrayToArrayStr(ResourceIDVar))
  else
    //the cast to AnsiString below is necessary or a Unicode string will sneak in and gum up the works
    AResult := PByteArray(AnsiString(VarToStr(ResourceIDVar)));
end;

exports ResourceIDBlobToString;

This method uses the cxFieldValueToVariant utility method found in cxSchedulerStorage to translate the string representation of the field value to a Delphi variant. We then use VarIsArray to test if the variant is an array. If it is not, we simply return the variant as a string. If the variant is a variant array, we will use the following method to parse it:

//input is a variant array of strings
//output is a comma delimited string composed of the members of the input array
function VarArrayToArrayStr(const ResourceIDArray: Variant): AnsiString;
var
  I: Integer;
begin
  Result := '';
  for I := VarArrayLowBound(ResourceIDArray, 1) to VarArrayHighBound(ResourceIDArray, 1) do
  begin
    if Result <> '' then
      Result := Result + ',';
    Result := Result + VarToStr(ResourceIDArray[I]);
  end;
end;

This simple function iterates through the variant array using VarArrayLowBound and VarArrayHighBound, building up a comma-delimited list of the resource ID’s.

And that’s it for the Delphi DLL.

Next we’ll create a new C# WinForms solution to test out our DLL. Click File>New>Project and select a Windows Forms Application.


I’ll skip the data access code as it’s straight-forward. The interesting bit here is the DllImport attribute we’ll use to call our Delphi DLL:

[DllImport("ExpressSchedulerInterop.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
static extern void ResourceIDBlobToString([MarshalAs(UnmanagedType.AnsiBStr)] string resourceID, [Out, MarshalAs(UnmanagedType.AnsiBStr)] out string result);

With this method defined properly, the following code can be used to read the resource data from the DB in C#:

string result = null;
ResourceIDBlobToString((string)reader["ResourceID"], out result);

You can download a Delphi scheduler app here, the Delphi scheduler interop project here, and the C# example data reader here.

UPDATE: I updated the code in this Blog post, along with the interop Delphi project source, to address a bug when using Unicode versions of Delphi. A cast to AnsiString is necessary or only the first character in the resource ID will be returned.

UPDATE #2: There’s a real-world example of this technique you can find here. It is an open source project for transferring data from ExpressScheduler to XtraScheduler.

Using the XAF Scheduler Module with Domain Components

It had been a while since I last looked at XAF from DevExpress, and since then the new Domain Components technology has been released in version 11.2. I decided to take a look at this new technology recently and see how exactly to make use of it.

The technology itself looks very promising, but makes using some of XAF’s modules require a little extra effort in some cases. This post will go over how to use the combination of Domain Components with the SchedulerWindowsFormsModule, which takes several steps beyond those required when using normal Domain Objects.

Start off by creating a new XAF Cross-Platform Application solution.


As with any XAF based project, build the solution first so that type information is available to the XAF model editor.

Expand the WinForms (Win) application project in the Solution Explorer and double-click WinApplication.cs. Side-note: on this designer you can select the Sql Connection and edit the connection string if necessary.

Locate the SchedulerWindowsFormsModule in the XAF Modules category of the Toolbox and drag to the Modules window in WinApplication.cs


Next, in the Solution Explorer, expand the common module project and double-click Module.cs. Under Exported Types, expand Referenced assemblies and then DevExpress.Persistent.Base.vXX.Y. Right-click IPersistentRecurrentEvent (the DC we’ll be using) and click Use Type In Application


Build the solution. This is necessary so that the newly included types are available in the model editors.

So far, this is very similar to using the Domain Objects. The exception being that we’ve included the Domain Component interfaces rather than the Domain Object classes (Event, Resource).

Now, right-click the Module.cs designer and click View Code. Add the following code:

        public override void Setup(XafApplication application)
        {
            base.Setup(application);

            //register scheduling Domain Components
            XafTypesInfo.Instance.RegisterEntity("Event", typeof(DomainComponents.Common.IPersistentRecurrentEvent));
            XafTypesInfo.Instance.RegisterEntity("Resource", typeof(DomainComponents.Common.IPersistentResource));
        }

This code is necessary with Domain Components to register the interfaces with XAF.

Next we’ll need to make some modifications to the model so that the scheduler user interface elements are displayed. These steps are taken care of automatically when using the Event Domain Object. Right-click the common module project in the Solution Explorer and click Open Model Editor.


Expand NavigationItems. Then, right-click Items, go to Add, and then NavigationItem.


Select the new navigation item and, on the right, under View, select IPersistentRecurrentEvent_ListView. If you do not see IPeristentRecurrentEvent_ListView, close the model editor, rebuild, and try again.


Back in the model editor tree, expand Views, followed by DomainComponents.Common, IPersistentRecurrentEvent_DetailView, Layout, Main, and finally SimpleEditors. Select IPersistentEvent and, on the right, change Caption to Event.


Again in the model editor tree, above Layout, expand Items. Find and delete the AppointmentId and Pattern items (normally hidden by the built in Event Domain Object).


And now run the WinForms project.


You can download the sample project here.

Adding Some Style to the VCL TileControl

In my previous post in the DevExpress VCL TileControl I laid out the basics of getting a Metro-inspired application functional. However, while the result definitely had function, it was a little short on “form”.

When using the VCL TileControl, odds are you will also want a Metro-inspired skin for your application. While the ExpressSkins Library does not currently ship with any Metro-inspired skins, the RealtorWorld demo that ships with the DevExpress VCL TileControl includes two such skins: MetroBlack and MetroWhite.

Making use of these skins in your own Metro-inspired VCL application is a cinch.

To get started, copy the two SKINRES files from the following path to your own application’s working directory:

C:Program FilesDeveloper Express.VCLExpressTile ControlDemosData

Next, locate the TdxSkinController component on the Tool Palette and add it to Form1 of the TileControlSample project created in my previous post. You can download the source to that project here.


Add a FormCreate handler to Form1 with the following code:

procedure TForm1.FormCreate(Sender: TObject);
begin
  dxTileControl1.LookAndFeel.NativeStyle := False; //so skins take affect
  dxSkinController1.SkinName := 'UserSkin'; //so we can load a .skinres
  dxSkinsUserSkinLoadFromFile('MetroBlack.skinres');
end;

And that’s all it takes to give our sample a dark, Metro-inspired skin.


Replace the reference to MetroBlack.skinres with MetroWhite.skinres in order to use the lighter Metro-inspired skin.

You can download the updated Delphi sample here.

Getting Started with the DevExpress VCL TileControl

In my previous posts I discussed the new “Server Mode” feature for the VCL grid from DevExpress found in version 12.1 of their VCL controls. Another great new feature found in version 12.1 is the new TileControl. This control lets any VCL developer start creating Metro-inspired UI’s in very little time with little-or-no code. Let’s see how!

Start off by creating a new VCL Forms Application. Afterward, create two new VCL forms by clicking File > New > VCL Form. Ensure all three forms will be automatically created by clicking Project>Options>Forms.


Switch to the Form2 and Form3 designers, setting their BorderStyle property to bsNone and Visible property to True. I also added a TShape to Form2 and Form3 with unique colors to make them easier to discern.

After customizing Form2 and Form3, switch back to the main form of the example, Form1. Under the “Dev Express” section of the Tool Palette, location the TdxTileControl and add it to the Form1 designer.


Right-click the TdxTileControl to display its context menu and use the Add Item menu item to add three tiles.


Select the first item in the TdxTileControl and inspect its properties. Expand the DetailOptions node. For DetailControl, select Form2. Note that you may need to add Unit2 and Unit3 to the uses clause of Unit1. Also, add a value for DetailOptions.Caption. Finally, set ShowTab to True.


Configure the second tile item in nearly the same way, only using Form3 instead of Form2.

For the third tile item, I’ll illustrate how to use a TFrame. Add a new TFrame to the project by clicking File>New>Other and selecting VCL Frame.


Switch to the designer for Frame1 and add another TShape with a unique color. Set the Align property on the TShape to alClient.


With the frame configured, switch back to the designer for Form1 and select the third tile item. Expand DetailOptions in the Object Inspector. This time leave DetailControl blank and set ShowTab to False. In the compiled example you’ll see the affect that the ShowTab property has.


Finally, click on the Events tab in the Object Inspector and add an event handler for OnClick.


In the event handler, use this small bit of code to check to see if DetailControl is assigned and, if not, create and assign an instance of TFrame4.

procedure TForm1.dxTileControl1dxTileControlItem3Click(
  Sender: TdxTileControlItem);
begin
  if Sender.DetailOptions.DetailControl = nil then
    Sender.DetailOptions.DetailControl := TFrame4.Create(Self);
end;

You’ll also need to add Unit4 to the uses clause of Unit1.

And that’s it! Run the sample and you’ll see your three tiles. You can rearrange them using drag-and-drop. Clicking any of the three tiles will animate in either Form2, Form3, or Frame4, depending on the tile. You’ll also see a nice set of tabs in the upper right. Here you’ll see that the third tile item did not get a tab due to setting ShowTab to false.


You can download the Delphi source code for this example here.

Getting Started with Server Mode for ExpressQuantumGrid

In my previous blog post I went over some of the performance benefits of the new “Server Mode” feature for the VCL grid from DevExpress. In this brief post, I’ll go over the steps needed to get started using this new feature. In this example I’ll be targeting Microsoft SQL Server using ADO.

You’ll want to start off by creating a new VCL Forms Application. Add a TcxGrid control to the form. Right-click the default grid level to invoke the level’s context menu. From there, create a new Server Mode grid view.


Next, drop a TADOConnection component on the form. It can be found in the dbGo section of the Tool Palette, or by using he Search box.


With the TADOConnection component selected, configure it by setting LoginPrompt to False and clicking the elipsis next to ConnectionString to configure the underlying connection.


As I mentioned, in this example I’m targeting Microsoft SQL Server. The project source linked at the end of the blog post contains SQL scripts for creating a sample table and filling it with data. Use the Data Link Properties dialog to configure the connection.


With the connection configured, locate the TdxServerModeADODataSource on the tool palette and drop it on the form. The “Server Mode” datasource is responsible for taking the needs of the TcxGrid view and creating SQL queries that return only the data necessary to render the results on-screen.


The data source only has a few properties. Start off by setting Options.SQLAdapter to “MSSQL Adapter”. If you don’t set the Options.SQLAdapter, trying to configure other properties will let you know you’ll need to assign that property first. Next, set the Connection, after which you can use the drop down lists to select your TableName and KeyFieldNames.


With the datasource setup, we’re in the home stretch. Select the “Server Mode” view by clicking the “cxGrid1ServerModeTableView1″ UI element on the TcxGrid control. With the view selected, expand the DataController node in the Object Inspector and assign the DataSource property.


Right-click the “cxGrid1ServerModeTableView1″ UI element on the TcxGrid control and click “Create Missing Columns” to have the grid automatically create the columns found in the underlying data.


And that’s it! Running the application will leave you with a “blazing-fast” grid capable of loading, sorting, grouping, and filtering millions of rows of data.


You can download the Delphi source code and SQL scripts here.

“Blazing-Fast” Data Binding for Large VCL Datasets

Version 12.1 of the DevExpress VCL controls is now available. One exciting feature that customers have been anticipating is called “Server Mode” for the VCL grid. This feature, available in the .NET grid from DevExpress, allows the control to bind to huge amounts of data and work fully featured with that data while maintaining solid performance.

I recently explored this new feature in a small sample created using Delphi XE2. To start with, I created a new table, LotsaRows, in a Microsoft SQL Server database. I then used a simple script to populate the table with one million rows.

Armed with some sample data, I created my Delphi project. The project consists of four different grid configurations:

  1. A normal TDBGrid *no sorting, grouping, filtering
  2. A TcxGrid in “Grid Mode” (View.DataController.GridMode set to True) *no sorting, grouping, filtering
  3. A “Fully Featured” TcxGrid
  4. A TcxGrid using the new “Server Mode”

The “Server Mode” feature is comprised of a few different components. There is a new TcxGrid view as well as new datasources that handle the querying of data. In my sample I used a TdxServerModeADODataSource for connecting to Microsoft SQL Server and a TcxGridServerModeTableView for my grid.

Fetching the data for the first three grids (which use traditional datasources) takes around 6 seconds for all one million rows on my setup. Binding both the TDBGrid and the TcxGrid in “Grid Mode” is nearly instant. Binding one million records to a TcxGrid setup for all features (sorting, grouping, filtering) takes around 20 seconds for me. And, with one million rows, even after loading that data the sorting and grouping can be sluggish.

The fourth configuration, the TcxGrid in “Server Mode”, is nearly instant to fetch the ADO data (compared to 6 seconds previously). In addition, binding the data to the TcxGrid control takes only 150-175 milliseconds (compared to 20 seconds). The sorting, grouping, and filtering is all much faster than the third configuration as well.

So how is this magic accomplished? Once configured, the TcxGridServerModeTableView will only request the data it needs, via the TdxServerModeADODataSource, in order to render data on screen. Initially, enough data is queried from the datasource to populate the visible rows, as well as determine things like the scrollbar position. As the user begins to make use of the features of the grid, the combination of the grid view and datasource will only query the pieces of information needed in order to perform the operation and render the results. For instance, clicking a column to sort the contents will only query those rows needed to render the results on screen, using an appropriate ORDER BY clause.

You can run a trace on SQL Server in order to see what some of these SQL queries look like:

SELECT TOP 128 "ID", "Column1", "Column2", "Column3", "Column4" FROM "LotsaRows"   ORDER BY "Column2" asc, "ID" asc
SELECT "ID" FROM (SELECT "ID", ROW_NUMBER() OVER(ORDER BY "Column2" asc, "ID" asc) as "DXROWNUMBER" FROM "LotsaRows" )DXRESULTSET WHERE DXRESULTSET.DXROWNUMBER > 395100 AND DXRESULTSET.DXROWNUMBER <= 395100 + 4151
exec sp_executesql N'SELECT "ID", "Column1", "Column2", "Column3", "Column4" FROM "LotsaRows" WHERE ("ID" IN ((@P1), (@P2), (@P3), (@P4), (@P5), ..., (@P55)))  ',N'@P1 nvarchar(38),@P2 nvarchar(38),@P3 nvarchar(38),@P4 nvarchar(38),@P5 nvarchar(38),...,@P55 nvarchar(38)',N'{6C2B027D-46C0-44E7-99FF-B60FBFB06091}',N'{477745E8-8011-45A8-AB6C-B6280E74BD87}',N'{5E49139F-67D8-4D8B-8B6C-B633698223E9}'...

You can download the Delphi source and SQL scripts for the example here.

Using XtraRichEdit to Edit HTML in VCL Applications

One request heard frequently from users of DevExpress’s VCL controls is for an HTML editing control. So far this has been deferred by the folks at DevExpress. However, they do make a bang-up .NET control called XtraRichEdit which has great HTML editing functionality. Wouldn’t it be great if we could easily embed that control in a VCL application?

It turns out this isn’t too tough using RemObjects’ Hydra product. Hydra is a plugin framework for both Delphi and .NET that lets you mix and match both managed and native hosts and plugins, visual and non-visual. This means you can make use of .NET visual controls in Delphi applications and vice-versa.

Let’s take a look at how easy this is to do (hint – very easy).

You’ll need Visual Studio, Delphi, the DevExpress WinForms controls, and Hydra all installed in the same environment. While it’s possible to do this with Delphi and Visual Studio on separate machines, it’s beyond the scope of this post.

Create a new project in Visual Studio using the “Plugin Module” template in the “RemObjects Hydra” category. Afterward, use the “Add>New Item” dialog to create a new “Visual Plugin”. Add a RichEditControl to the new design surface and dock it in its parent.

This alone is enough to yield a plugin module that can be loaded in a Delphi application and display a working RichEditControl. However, there would be no way to access the richedit’s HTML text. For this we will need to use a custom interface. This is really easy to do.

Add the following interface declaration to the top of the code-behind:

    [Guid("4033C8A9-8A7C-4DE4-864C-B8F60EFFBDD7")]
    public interface IRichEditPlugin : IHYCrossPlatformInterface
    {
        string GetHtmlText();
        void SetHtmlText(string text);
    }

This will require using RemObjects.Hydra.CrossPlatform and System.Runtime.InteropServices. Both the Guid and descending from IHYCrossPlatformInterface are required by Hydra. Finally, implement the interface:

    public partial class RichEditPlugin : VisualPlugin, IRichEditPlugin
    ...
        public string GetHtmlText()
        {
            return richEditControl1.HtmlText;
        }

        public void SetHtmlText(string text)
        {
            richEditControl1.HtmlText = text;
        }

And that’s it for the .NET side of things.

On the Delphi side of things, create a new VCL forms project. Add a THYModuleManager, TPanel, TMemo, and two TButtons.

Click the Hydra menu followed by Import Interfaces from .NET Assemblies. Browse for the assembly created above and click Import on the dialog listing the IRichEditPlugin interface. Then, click the Hydra menu followed by Hydra Package Settings. Select “Build with Hydra Core Packages” and click OK.

Adding a minimal amount of code will get the RichEditControl showing:

procedure TForm2.FormCreate(Sender: TObject);
begin
  HYModuleManager1.LoadModule('RichEditModule.dll');
  HYModuleManager1.CreateVisualPlugin('RichEditModule.RichEditPlugin', FRichEditPlugin);
  FRichEditPlugin.ShowParented(Panel1);
end;

procedure TForm2.FormDestroy(Sender: TObject);
begin
  FRichEditPlugin := nil;
  HYModuleManager1.UnloadModules;
end;

FRichEditPlugin is a private field declared as IHYVisualPlugin.

After you copy the assembly created in .NET (RichEditModule.dll in my example) to the same path as your debug executable, running the application will now show the Delphi application with the .NET RichEditControl embedded and fully functional.

Adding a bit more code will allow getting and setting the HTML text in the .NET RichEditControl using the text entered in the TMemo:

//Set button
procedure TForm2.Button1Click(Sender: TObject);
var
  RichEditPlugin: IRichEditPlugin;
begin
  if Supports(FRichEditPlugin, IRichEditPlugin, RichEditPlugin) then
    RichEditPlugin.SetHtmlText(Memo1.Text);
end;

//Get button
procedure TForm2.Button2Click(Sender: TObject);
var
  RichEditPlugin: IRichEditPlugin;
begin
  if Supports(FRichEditPlugin, IRichEditPlugin, RichEditPlugin) then
    Memo1.Text := RichEditPlugin.GetHtmlText;
end;

This new code will require adding the “_Import.pas” unit generated when you imported the .NET interface to your uses clause.

And that’s it. Press the run button and then try the Get and Set buttons along with editing text in the RichEditControl.

XtraRichEdit in a VCL App

This is pretty powerful stuff thanks to Hydra and the XtraRichEdit, and very easy to do! You can download the C# and Delphi source code here.

Accessing ExpressScheduler Recurrence Information from .NET

One challenge I’ve come up against recently is using C# to read the scheduler information saved by the DevExpress ExpressScheduler VCL control. Most of the data is fairly straight forward to read. However, there are two exceptions: recurrence information and associated resources.

This post will discuss how to read the recurrence information. This can be done directly in C#. A future post will explore how to read the associated resources. If your Delphi application only allows one resource to be associated to an event this isn’t an issue. However, if you allow multiple resources per event these are stored as Delphi variants in the DB and require Delphi to read the values out.

The recurrence information, on the other hand, is stored in a packed Delphi record which is in turn stored directly as an array of bytes in the DB field. The Delphi record is called TcxSchedulerEventRecurrenceInfoData and is defined in cxSchedulerStorage.pas:

TcxSchedulerEventRecurrenceInfoData = packed record
  Count: Integer;
  DayNumber: Integer;
  DayType: TcxDayType;
  Finish: TDateTime;
  OccurDays: TDays;
  Periodicity: Integer;
  Recurrence: TcxRecurrence;
  Start: TDateTime;
  YearPeriodicity: Integer;
  Reserved1: Byte;
  DismissDate: Integer;
end;

In order to read the recurrence information in .NET, this record and its associated types must be translated into their .NET counterparts. Here is an example of an equivalent C# struct:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
struct SchedulerEventRecurrenceInfoData
{
    public int Count;
    public int DayNumber;
    public DayType DayType;
    public double Finish;
    public Days OccurDays;
    public int Periodicity;
    public Recurrence Recurrence;
    public double Start;
    public int YearPeriodicity;
    public byte Reserved1;
    public int DismissDate;
}

The rest of the C# types can be found in the accompanying sample.

With these types in place, the only thing left is some code to convert the recurrence information from the string value stored in the DB to the SchedulerEventRecurrenceInfoData struct. This post on StackOverflow gives a simple solution for doing this:

T ByteArrayToStructure(byte[] bytes) where T: struct
{
    GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
    T stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
    handle.Free();
    return stuff;
}

There is a working Delphi sample here and the .NET sample app can be found here.

UPDATE: There’s a real-world example of this technique you can find here. It is an open source project for transferring data from ExpressScheduler to XtraScheduler.

Smart Phone Style Lists with QuantumGrid

A poster on the Developer Express forums recently inquired on how to use the VCL QuantumGrid to mimic a smart phone styled list. You can see an example of the desired appearance here:

Smart Phone List Example

Notable aspects of this style are:

  • Data in a single row arranged both vertically and horizontally
  • Varying cell heights within a single row
  • Single row selection (rather than cell selection)
  • Independent cell styles
  • No column headers or cell captions

Luckily the QuantumGrid is up to the challenge. Here is an example of a smart phone styled list using the QuantumGrid and Delphi XE2:

QuantumGrid Smart Phone List

This can be accomplished using the “banded” table view in the QuantumGrid. A banded table view lets you group columns together into bands. Each band can have a variable number of vertically or horizontally stacked columns. The above example is composed of three bands and four columns: one column (with double-height) in the first band, two columns stacked vertically in the second, and a single column in the third band.

Adding and organizing bands and columns is made easy using the right-click context menu of the QuantumGrid. Starting with a simple banded table view, here is a brief video that shows how easy it is to add and layout the bands and columns necessary to achieve the above affect.

Once the banded table view has the proper bands and columns added, the following settings should be applied to the table view in the object inspector:

OptionsData.Editing = False
OptionsSelection.CellSelect = False
OptionsView.ColumnAutoWidth = True
OptionsView.GridLines = glNone
OptionsView.GroupByBox = False
OptionsView.Header = False
OptionsView.RowSeparatorColor = clGrayText
OptionsView.RowSeparatorWidth = 1
OptionsView.BandHeaders = False

With these settings in place, all that is needed is a bit of sample data and some contact thumbnails to complete the effect. You can download the source of this sample project here.

Updated 5/10/2012: DevExpress employee Alex M had this to say on the forums:

I think that making CountColumn right aligned will add a final touch to the look and feel.
TextEditProperties.Alignment.Horz := taRightJustify;
Also, I believe using a band’s context menu introduced in DevExpress VCL Build v2011 vol 2  (try once, love it forever :) ) would simplify column/band creation and arrangement shown in the video.

I’ve updated the sample and video to reflect Alex’s suggestions. Thanks Alex!