segunda-feira, 17 de fevereiro de 2014

Criando um controle data-aware

Depois de algum tempo, longe do blog, eu volto. Mas agora resolvi abordar um assunto que poucos programadores Delphi conhecem: a classe TDataLink. Vou explicar rapidamente o que esta classe faz.
A conexão entre um datasource e um controle data-aware (consciente de dados) é feita através de um data link, um descendente da classe TDataLink. O controle data-aware deve criar e gerenciar o data link. Logo, para criar um controle que tem consciência de dados, você deve adicionar um data link ao seu componente e manipular algumas propriedades deste data link interno.
O dataset utiliza o data link para notificar o controle data-aware de qual algo aconteceu, como por exemplo, a conexão ficou ativa, os dados mudaram, etc. O controle data-aware utiliza o data link para exigir dados do dataset ou para mudá-los e notificar o dataset que tal mudança ocorreu.
Falando assim até parece fácil, né? Mas na vida real as coisas são um pouco mais complicadas porque você só pode ter um data link por controle data-aware, no entanto você pode ligar vários datasources à um dataset e você geralmente liga vários controles data-aware à um datasource, ....
A classe TDataLink é declarada na unit DB (Delphi 7), Data.DB no XE em diante. Esta classe tem alguns métodos que atuam quase como eventos e são tipo "canivete suíço" e que podem ser redefinidos em classes descendentes para interceptar operações do usuário ou então eventos do datasource. Como de praxe, vamos dar uma olhada na definição da classe:

TDataLink = class(TPersistent)

protected

    procedure ActiveChanged; virtual;

    procedure CheckBrowseMode; virtual;

    procedure DataEvent(Event: TDataEvent; Info: NativeInt); virtual;

    procedure DataSetChanged; virtual;

    procedure DataSetScrolled(Distance: Integer); virtual;

    procedure EditingChanged; virtual;

    procedure FocusControl(Field: TFieldRef); virtual;

    function GetActiveRecord: Integer; virtual;

    function GetBOF: Boolean; virtual;

    function GetBufferCount: Integer; virtual;

    function GetEOF: Boolean; virtual;

    function GetRecordCount: Integer; virtual;

    procedure LayoutChanged; virtual;

    function MoveBy(Distance: Integer): Integer; virtual;

    procedure RecordChanged(Field: TField); virtual;

    procedure SetActiveRecord(Value: Integer); virtual;

    procedure SetBufferCount(Value: Integer); virtual;

    procedure UpdateData; virtual;

    property VisualControl: Boolean read FVisualControl write FVisualControl;

Agora vejamos a enumeração TDataEvent:

TDataEvent = (deFieldChange, deRecordChange, deDataSetChange,
    deDataSetScroll, deLayoutChange, deUpdateRecord, deUpdateState,
    deCheckBrowseMode, dePropertyChange, deFieldListChange,
    deFocusControl, deParentScroll, deConnectChange, deReconcileError,
    deDisabledStateChange);

Esta enumeração na verdade lista todos os eventos que são manipulados pelo método DataEvent da classe TDataLink. Este método (privado no Delphi 7 e protegido no XE), funciona como um procedimento de janela para o DataSource. O datasource chama seu método NotifyDataLinks para transferir o evento para cada data link associado à ele, só então ele dispara seus método OnDataChange e OnUpdateData. Interessante, não?
Isto é importante: RARAMENTE você vai usar a classe TDataLink diretamente. Sempre que precisar, é melhor derivar uma nova classe e é o que é feito com os controles data-aware do Delphi (menos o DBGrid). Controles tais como DBEdit, DBCombo, etc... eles usam uma classe derivada de TDataLink: TFieldDataLink. Esta classe é muito útil para controles que necessitem trabalhar com um registro por vez (daí o motivo de DBGrid não utilizá-la).

Nenhum comentário:

Postar um comentário