Создание компонентов для работы с базами данных
|
Базу селектом не испортишь.
|
Обзор
Данный документ описывает минимально необходимые шаги, необходимые для
создания компонента для работы с базами данных, который может отображать данные
отдельного поля. Примером такого компонента может служить панель со свойствами
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.
|
|