2010. október 23., szombat

Accessing hidden properties


Problem/Question/Abstract:

How can I access the InplaceEditor property of a Grid?

Answer:

Some components have useful properties, but for some reason they were declared in their protected section, so they are not readily available to the programmer. For example, TStringGrid, TDrawGrid, TDBGrid and in general any descendant of TCustomGrid has an InplaceEditor property that represents the text edit box used for editing cell values. However you can't access this property directly because it has been declared as protected.

The easiest workaround to this problem is subclassing (deriving) your component with the only purpose or publishing the protected property. For example:

type
  TDBGridX = class(TDBGrid)
  public
    property InplaceEditor;
  end;

We don't need to intall this new component and register it in the components palette (which I consider too much of a bother for such a little thing). Instead, any time we want to access this property, we can just cast the object (for example DBGrid1) to our new class. For example:

TDBGridX(DBGrid1).InplaceEditor.SelectAll;

Note: InplaceEditor will be Nil until the first time EditorMode is set to True (either by code or when the user presses F2).

But use the protected property always cause some fault unexpectable.Sush as the Fixcols property. How to resolve it?

The properties were left protected for some reason, usually this being the fact that they are not safe to use directly. There are some limitations when accessing protected fields, properties or methods and normally these limitations are documented (they are not so much "unexpectable").

For example, about the inplace editor the documentation says:

   "The inplace editor is created the first time the grid is put in edit mode."

This means that before the first time the grid is put in edit mode, a code like the following will certainly generate an
Access Violation:

TDBGridX(DBGrid1).InplaceEditor.SelectAll;

You can solve this problem by first checking if InplaceEditor is not Nil:

if TDBGridX(DBGrid1).InplaceEditor <> nil then
  TDBGridX(DBGrid1).InplaceEditor.SelectAll;

About FixedCols, the documentation says:

"Grids must include at least one scrolling column. Do not set FixedCols to a value greater than ColCount - 1."

This means that for instance the following code will raise an EInvalidGridOperation exception if ColCount <= 2:

TDBGridX(DBGrid1).FixedCols := 2;

For example if you create columns automatically from a Dataset associated with a DataSource, then you should first open the Dataset to let the columns be created, and only then you can set the FixedCols property. For example:

Table1.Active := True;
TDBGridX(DBGrid1).FixedCols := 2;

In conclusion, you should check the documentation first before using the protected properties since normally they have some limitation. As I've shown, the way to circunvent it depends on the case and there is no general rule. There may be also some undocumented problems and side effects and when they appear generally you should check the source code of the component to get an idea of how to avoid or fix them.

Copyright (c) 2001 Ernesto De Spirito
Visit: http://www.latiumsoftware.com/delphi-newsletter.php

Nincsenek megjegyzések:

Megjegyzés küldése