Советы по Delphi

         

Создание компонентов для работы с базами данных


Тема: Создание компонентов для работы с базами данных, позволяющих работать с самими данными

Обзор

Данный документ описывает минимально необходимые шаги, необходимые для создания компонента для работы с базами данных, который может отображать данные отдельного поля. Примером такого компонента может служить панель со свойствами DataSource и DataField, похожая на компонент TDBText. Для получения дополнительных примеров обратитесь к Руководству по написанию компонентов "Making a Control Data-Aware".

Как пользоваться данным документом

Для наилучшего понимания данного документа, вы должны быть знакомы с механизмом функционирования элементов управления для работы с базами данных и основополагающими принципами создания компонент, такими, как

  • создание компонентов на основе существующих

  • перекрытие конструкторов и деструкторов
  • создание новых свойств
  • чтение и запись значений свойств
  • назначение обработчиков событий
  • Основные шаги по созданию компоненты, осуществляющей навигацию по данным

    • Создайте или наследуйте компонент, который допускает свое отображение, но не ввод данных. Например, вы могли бы использовать компонент TMemo с установленным в True свойством ReadOnly. В примере, приведенном в данном документе, мы используем TCustomPanel. TCustomPanel позволяет себя отображать, но не вводить данные.

  • Добавьте к вашему компоненту data-link object (объект для связи с данными). Данный объект позволяет управлять связью между компонентом и таблицей базы данных.
  • Добавьте к компоненту свойства DataField и DataSource.
  • Добавьте методы для получения и установления DataField и DataSource.


  • Добавьте к компоненту метод DataChange, позволяющий управлять событиями OnDataChange объекта data-link.
  • Перекройте конструктор компонента для создания datalink и перехвата метода DataChange.
  • Перекройте деструктор компонента для очищения datalink.
  • Создание TDBPANEL

    • Создайте или наследуйте компонент, который допускает свое отображение, но не ввод данных. В качестве отправной точки для нашего примера мы будем использовать TCustomPanel.

    Выберите соответствующий пункт меню для создания нового компонента (он меняется от версии к версии Delphi), определите TDBPanel как имя класса, и TCustomPanel в качестве наследуемого типа. Определите любую страницу Палитры компонентов.

  • Добавьте DB и DBTables в список используемых модулей.
  • Добавьте data-link объект в секцию private вашего компонента. Данный пример отображает данные одного поля, поэтому мы используем TFieldDataLink для обеспечения связи между нашим новым компонентом и DataSource. Имя нового data-link объекта - FDataLink.
  •     { пример } private FDataLink: TFieldDataLink;

  • Добавьте к компоненту свойства DataField и DataSource. Мы добавим соответствующий код для методов записи/чтения в последующих шагах.
  • Примечание: Наш новый компонент будет иметь свойства DataField и DataSource, FDataLink также будет иметь собственные свойства DataField и Datasource.

        { пример } published property DataField: string read   GetDataField write  SetDataField; property DataSource: TDataSource read   GetDataSource write  SetDataSource;

  • Добавьте частные методы для чтения/записи значений свойств DataField и DataSource, и свойств DataField и DataSource для FDataLink.
  •     { пример } private FDataLink: TFieldDataLink; function GetDataField: String; function GetDataSource: TDataSource; procedure SetDataField(Const Value: string); procedure SetDataSource(Value: TDataSource); . . implementation . . function TDBPanel.GetDataField: String; begin Result := FDataLink.FieldName; end;
    function TDBPanel.GetDataSource: TDataSource; begin Result := FDataLink.DataSource; end;
    procedure TDBPanel.SetDataField(Const Value: string); begin FDataLink.FieldName := Value; end;
    procedure TDBPanel.SetDataSource(Value: TDataSource); begin FDataLink.DataSource := Value; end;

  • Добавьте частный метод DataChange, назначая событие объекта datalink OnDataChange. В методе DataChange добавьте код для отображения данных поля актуальной базы данных, связь с которой обеспечивает объект data-link. В нашем примере мы назначаем значение поля FDataLink заголовку панели.
  •     { пример } private . . procedure DataChange(Sender: TObject);
    implementation . . procedure TDBPanel.DataChange(Sender: TObject); begin if FDataLink.Field = nil then Caption := ''; else Caption := FDataLink.Field.AsString; end;

  • Перекройте метод конструктора компонента Create. При реализации Create, создайте объект FDataLink и назначьте частный метод DataChange событию FDataLink OnDataChange.
  •     { пример } public constructor Create(AOwner: TComponent); override; . . implementation . . constructor TMyDBPanel.Create(AOwner: TComponent); begin inherited Create(AOwner); FDataLink := TFieldDataLink.Create; FDataLink.OnDataChange := DataChange; end;

  • Перекройте метод деструктора компонента Destroy. При реализации Destroy, установите OnDataChange в nil (чтобы избежать GPF), и освободите FDatalink.
  •     { пример } public . . destructor Destroy; override; . . implementation . . destructor TDBPanel.Destroy; begin FDataLink.OnDataChange := nil; FDataLink.Free; inherited Destroy; end;

  • Сохраните модуль и установите компонент (смотрите документацию Users Guide и Component Writers Guide для получения дополнительной информации по сохранению модулей и установке компонентов).
  • Для тестирования функциональности компонента расположите на форме компоненты TTable, TDatasource, TDBNavigator и TDBPanel. Установите TTable DatabaseName и Tablename в 'DBDemos' и 'BioLife', а свойство Active в True. Установите свойство TDatasource Dataset в Table1. Установите TDBNavigator и свойство TDBPanel DataSource в Datasource1. Имя TDBpanel DataField должно быть установлено в 'Common_Name'. Запустите приложение и, используя навигатор и перемещаясь по записям, убедитесь в том, что TDBPanel обнаруживает изменение данных и отображает значение соответствующего поля.
  • Полный код компонента

        unit Mydbp;

    interface

    uses

    SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, DB, DBTables;
    type
    TDBPanel = class(TCustomPanel) private FDataLink: TFieldDataLink; function GetDataField: String; function GetDataSource: TDataSource; procedure SetDataField(Const Value: string); procedure SetDataSource(Value: TDataSource); procedure DataChange(Sender: TObject); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published property DataField: string read   GetDataField write  SetDataField; property DataSource: TdataSource read   GetDataSource write  SetDataSource; end;
    procedure Register;
    implementation

    procedure Register
    ; begin RegisterComponents('Samples', [TDBPanel]); end;
    function TDBPanel.GetDataField: String; begin Result := FDataLink.FieldName; end;
    function TDBPanel.GetDataSource: TDataSource; begin Result := FDataLink.DataSource; end;
    procedure TDBPanel.SetDataField(Const Value: string); begin FDataLink.FieldName := Value; end;
    procedure TDBPanel.SetDataSource(Value: TDataSource); begin FDataLink.DataSource := Value; end;
    procedure TDBPanel.DataChange(Sender: TObject); begin if FDataLink.Field = nil then Caption := '' else Caption := FDataLink.Field.AsString; end;
    constructor TDBPanel.Create(AOwner: TComponent); begin inherited Create(AOwner); FDataLink := TFieldDataLink.Create; FDataLink.OnDataChange := DataChange; end;
    destructor TDBPanel.Destroy; begin FDataLink.Free; FDataLink.OnDataChange := nil; inherited Destroy; end;
    end.

    [001083]



    Содержание раздела