Home Put a devexpress dbgridview cell's contents with different textformats
Reply: 3

Put a devexpress dbgridview cell's contents with different textformats

Mohamed Benattou
Mohamed Benattou Published in 2017-09-11 11:25:22Z

With Devexpress cxGrid, I've a tablegridview showing a db table of three fields of varchar(30); ID, NAME and DESCRIPTION

Actual cxgrid appearance : ID NAME DESCRIPTION 1 Name 1 Description 1 2 Name 2 Description 2 . ... ... X Name X Description 3

and, i want the two fields to be concatenated and separated by #13 (in two lines), and each line with a special text format (ex. the 1st with bold and the 2nd with italic).

The cxgrid's appearance I look for : ID NAME and DESCRIPTION (just one field instead of two) 1 Name 1 Description 1 2 Name 2 Description 2 . Name ... Description ... 3 Name 3 Description ...

Any help will be appreciated !

MartynA Reply to 2017-09-11 20:05:36Z

I have tried both possibilities suggested in comments, i.e. using custom drawing in a standard DBTableView and using a DBBandedTableView and neither seems to offer an ideal solution out of the box.

Using a DBTableView quickly runs into the sand for a non-expert like me:

  • Although it is straightforward to draw the Description text below the Name text, it is fraught with difficulties, like how to pick up the bounds of the Name cell while drawing the Description one and how to avoid the grid drawing a residual outline of what would have been the Description cell and header if the Description were drawn normally.

Using a DBBandedTableView seems to converge on a workable solution with far fewer details to address. Try the following:

  • Add a ClientDataSet, CDS1 to your form, add persistent fields to it for the ID, Name and Description fields.

  • Add a DBBandedTableView to your cxGrid and connect it to CDS1 using a TDataSource.

  • Create two bands in it and give them captions Band and Band2 for ease of reference.

  • Create columns for the ID, Name and Description columns. Set their Properties property to TextEdit.

  • In the DBBandedTableView editor, add the ID column to Band and the Name and Description columns to Band2 using to BandIndex sub-property of the columns' Position property. Also set the RowIndex sub-property of the Description column to 1, to cause it to be positioned below the Name field.

Set up the form's code as shown below, compile and run. As you can see, all the custom drawing code does is to set the font style of the Name and Description fields.

The result is maybe not quite as you've specified, but I'll leave you to iron out the remaining details - if you get stuck, say so.

  TForm1 = class(TForm)
    CDS1: TClientDataSet;
    CDS1ID: TAutoIncField;
    DS1: TDataSource;
    DBNavigator1: TDBNavigator;
    CDS1Name: TStringField;
    CDS1Description: TStringField;
    cxGrid1Level1: TcxGridLevel;
    cxGrid1: TcxGrid;
    cxGrid1DBBandedTableView1: TcxGridDBBandedTableView;
    cxGrid1DBBandedTableView1ID: TcxGridDBBandedColumn;
    cxGrid1DBBandedTableView1Name: TcxGridDBBandedColumn;
    cxGrid1DBBandedTableView1Description: TcxGridDBBandedColumn;
    procedure FormCreate(Sender: TObject);
    procedure CustomDrawCell(
      Sender: TcxCustomGridTableView; ACanvas: TcxCanvas;
      AViewInfo: TcxGridTableDataCellViewInfo; var ADone: Boolean);

  Form1: TForm1;


procedure TForm1.CustomDrawCell(Sender:
    TcxCustomGridTableView; ACanvas: TcxCanvas; AViewInfo:
    TcxGridTableDataCellViewInfo; var ADone: Boolean);
  ACol : TcxGridDBBandedColumn;
  ACol := TcxGridDBBandedColumn(AViewInfo.Item);
  if ACol = cxGrid1DBBandedTableView1Name then
    ACanvas.Font.Style := ACanvas.Font.Style + [fsBold]
  if ACol = cxGrid1DBBandedTableView1Description then
    ACanvas.Font.Style := ACanvas.Font.Style + [fsItalic];

procedure TForm1.FormCreate(Sender: TObject);
  i : Integer;


  CDS1.InsertRecord([1, 'Name1', 'Description1']);
  CDS1.InsertRecord([2, 'Name12', 'Description2']);


  cxGrid1DBBandedTableView1ID.PropertiesClassName := 'TcxTextEditProperties';
  cxGrid1DBBandedTableView1ID.OnCustomDrawCell := CustomDrawCell;

  cxGrid1DBBandedTableView1Name.PropertiesClassName := 'TcxTextEditProperties';
  cxGrid1DBBandedTableView1Name.OnCustomDrawCell := CustomDrawCell;

  cxGrid1DBBandedTableView1Description.PropertiesClassName := 'TcxTextEditProperties';
  cxGrid1DBBandedTableView1Description.OnCustomDrawCell := CustomDrawCell;

Marc Guillot
Marc Guillot Reply to 2017-09-12 09:19:46Z

A CustomDrawCell looks like an awfully burdensome solution for such a simple task.

The ideal solution would be for the TCxGrid having HTML columns, so you would just show on them a calculated field such as (replacing [] by <>) :

[html] [b] Name 1 [/b] [br] [i] Description 1 [/i] [/html]

The problem is that TCxGrid doesn't have HTML Columns, but as others have said, you have RichEdit Columns available. So you can also build this solution using RTF instead of HTML.

Use Word (or Write, on the Windows folder) to create a sample and look for the RTF representation of your text :

{\rtf1\ansi\ansicpg1252\deff0\deflang3082{\fonttbl{\f0\fnil\fcharset0 Calibri;}}
\viewkind4\uc1\pard\sa200\sl276\slmult1\lang10\b\f0\fs22 Name 1\par
\b0\i Description 1\i0\par

Now add a calculated field to your dataset returning this RTF representation of the formatted text that you want to show :

procedure TMyForm.MyQueryCalcFields(DataSet: TDataSet);
var FormattedText: string;
  FormattedText := '{\rtf1\ansi\ansicpg1252\deff0\deflang3082{\fonttbl{\f0\fnil\fcharset0 Calibri;}}' + sLineBreak +
                   '\viewkind4\uc1\pard\sa200\sl276\slmult1\lang10\b\f0\fs22 ' +
                   Dataset.FieldByName('Name').AsString + '\par' + sLineBreak +
                   '\b0\i ' + Dataset.FieldByName('Description').AsString + '\i0\par' + sLineBreak +

  Dataset.FieldByName('FormattedText').Value := FormattedText;    

Finally you just need to set the Properties of a Column as RichEdit, and binding this FormattedText to that column would give you the desired result.

Mohamed Benattou
Mohamed Benattou Reply to 2017-09-20 08:33:55Z

Finally, with some difficulties, and with the help of someone, this is the perfect solution with the OnCustomDraw instead of using BandedTableView, RichEditColumn or the Preview approaches.

procedure TForm1.cxGrid1DBTableView1NameCustomDrawCell(
  Sender: TcxCustomGridTableView; ACanvas: TcxCanvas;
  AViewInfo: TcxGridTableDataCellViewInfo; var ADone: Boolean);
Function VarToText(AVal: Variant): String;
If VarIsNull(AVal) 
  Then Result := ''
  Else Result := VarToStr(AVal);
  AValue1, AValue2: Variant;
  AText: String;
  ARect: TRect;
  ARect := AViewInfo.ClientBounds;
  AValue1 := Sender.DataController.Values[AViewInfo.GridRecord.Index, 
  AValue2 := Sender.DataController.Values[AViewInfo.GridRecord.Index, 
  ACanvas.Font.Style := [fsBold];
  If VarIsNull(AValue1) 
    Then Begin
           AText := VarToText(AValue2);
           ACanvas.Font.Style := [fsItalic];
           ACanvas.DrawTexT(AText, ARect, taLeftJustify, vaCenter, True, 
    Else If VarIsNull(AValue2) 
      Then Begin
             AText := VarToText(AValue1);
             ACanvas.Font.Style := [fsBold];
             ACanvas.DrawTexT(AText, ARect, taLeftJustify, vaCenter, True, 
      Else Begin
             ACanvas.DrawTexT(VarToText(AValue1), ARect, taLeftJustify, 
                              vaTop, True, false);
             ARect.Top := ARect.Top + 

             ACanvas.Font.Style := [fsItalic];
             ACanvas.DrawTexT(VarToText(AValue2), ARect, taLeftJustify,               
             vaBottom, True, False);
  ADone := True;

And, I'm here for any clarification.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.306469 second(s) , Gzip On .

© 2016 Powered by cudou.com design MATCHINFO