Positioning in a grid.

By: Philippe Randour

Abstract: When performing a search on a dataset connected to a TDBGrid, the positioning in the grid is done in the middle of the visible rows, which might not be adequate for your application. This article presents a way to change this.

Positioning in a grid.

Delphi, TDBGrid

Positioning in a grid.

by Philippe Randour (philippe_randour@hotmail.com)

The problem

Imagine that you want to perform a search on a TTable component connected to a TDBGrid component. You will then use, for instance, the method Locate of the TTable component. The net result will be that the found record will appear in the middle of the visible rows in the grid. Now, imagine that the specifications for your application require that the found record be in top of the list of visible rows. What will you do? In fact, you will have to modify the natural behavior of the grid component to achieve this result. It will be done by scrolling down the view on the table data. And how will you do that?

The solution

The solution lies in the MoveBy method of the TTable component. The purpose of this method is to position the cursor on a record relative to the current record in the dataset, thus making the TDBGrid scroll accordingly. Its almost perfect but you also want to keep the same current record. So you will have to call this method twice. The first one to scroll down the view to make your record the first visible in the grid, the second one to make it the current record again. I can see some of you saying: "Its a great idea but we lack a property giving us the number of visible rows in a TDBGrid". You are right but a possibility exists if you dig a little bit in the VCL hierarchy for the TDBGrid. TDBGrid is descending from TCustomGrid, which has a property called VisibleRowCount. Unfortunately, this property is protected, so you cannot access it directly in your code. If you try, the compiler will give you an "Undeclared identifier: VisibleRowCount" error. Its because a protected property is only accessible by code that appears in the same unit. To turn around this problem, you will create a derived class whose sole purpose will be to make a cast of your grid to the new class and access the protected property through it. And voil`, problem solved!

You can see it applied in the following code:

type
  TGridCracker = class(TCustomGrid);


begin
  Table.Locate('Common_Name','Firefish',[]);
  { Change the current record to a record not currently visible
    and located VisibleRowCount-1 rows farther }
  Distance := Table.MoveBy(TGridCracker(DBGrid).VisibleRowCount-1);
  { Make the previously found record the active one. The active 
    record will then be the first visible in the grid }
  Table.MoveBy(-Distance);
end;

Server Response from: SC2