по значениям поля набора данных 6 глава




Для блокирования элементов управления можно использовать компонент ActionList, предназначенный для синхронизации элементов управления.

Блокировка попыток пользователя изменить немодифицируемый набор данных должна выполняться также при добавлении и удалении записей.

При выполнении метода Edit непосредственно перед переводом набора данных в режим редактирования возникает событие BeforeEdit, которое можно ис­пользовать для проверки возможности перехода в этот режим. Например, при попытке пользователя редактировать запись ему может быть предложено под­твердить свои действия. Для отмены процесса редактирования в обработчике события BeforeEdit можно сгенерировать "тихое" исключение.

При переходе в режим редактирования с помощью кнопки Button проверку его допустимости можно выполнить в обработчике события ее нажатия. Однако обычно удобнее использовать обработчик события BeforeEdit, т. к. оно гене­рируется при переводе набора данных в режим редактирования любым спосо­бом. Вот пример соответствующей процедуры:

procedure TForml.TablelBeforeEdit(DataSet: TDataSet); begin


Глава 7. Навигационный доступ к данным с помощью BDE


211


if MessageDlg('Выполнить редактирование?',

reconfirmation, [mbYes, mbNo], 0) о mrYes then Abort; end;

После перевода набора данных в режим редактирования можно с помощью ин­струкций присваивания изменять значения полей текущей записи. При этом нужно учитывать тип поля, выполняя при необходимости операции приведения типов. Например:

Tablel.FieldByName('City').AsString:= Editl.Text;

Tablel.FieldByName('Code').AsInteger:= StrToInt(Edit2.Text);

Tablel.FieldByName('Price').AsFloat:= StrToFloat(Edit3.Text);

Перед выполнением приведенных инструкций набор данных Tablel должен находиться в режиме редактирования или вставки. Если редактор Edit2 или Edit3 содержит данные в формате, не соответствующем целому и веществен­ному числам, то генерируется исключение.

Для проверки, вносились ли изменения в запись, можно проанализировать свойство Modified типа Boolean. Если свойство имеет значение True, то было изменено значение как минимум одного поля текущей записи.

После ввода информации сделанные изменения должны быть или подтвержде­ны, или отменены.

Метод Post записывает модифицированную запись в таблицу БД, снимает блоки­ровку записи и переводит набор данных в режим просмотра. Если набор данных не находился в режиме редактирования, то вызов метода Post приведет к гене­рации исключения. Перед его выполнением автоматически вызывается обработ­чик события BeforePost типа TDataSetNotifyEvent, а сразу после выполне­ния — обработчик события AfterPost типа TDataSetNotifyEvent. Используя событие BeforePost, можно проверить сделанные изменения и при необходи­мости отменить их, например, прервав выполнение метода с помощью вызова "тихого" исключения.

Рассмотрим процедуру, в которой осуществляется редактирование записей:

procedure TForial.btnPriceChangeClick(Sender: TObject); var bml: TBookmark; coeff, x: real; begin

// Проверка, является ли набор данных модифицируемым if not Tablel.CanModifу then begin

MessageDlg('Записи изменять нельзя!', mtError, [mbOK], 0);

exit;

end; // Получение коэффициента try

coeff:= StrToFloat(Editl.Text);


212


Часть II. Технологии доступа к данным


except

MessageDlg('Неправильный коэффициент!' + #13#10 + 'Повторите ввод.', mtError, [mbOK], 0); if Editl.CanFocus then Editl.SetFocus;

exit; end; // Запоминание позиции текущего указателя bml: = Tablel.GetBookmark;

// Отключение отображения записей визуальными компонентами Tablel.DisableControls; // Перебор всех записей Tablel.First; while not Tablel.EOF do begin

// Чтение цены из очередной записи

х:= Tablel.FieldByName('Price').AsFloat;

// Пересчет цены

x:= x * Coeff;

// Изменение цены в текущей записи

Tablel.Edit;

Tablel.FieldByName('Price').AsFloat:= x;

Tablel.Post;

// Переход к следующей записи

Tablel.Next;

end; // Восстановление позиции текущего указателя //и отображение записей визуальными компонентами if Tablel.BookmarkValid(bml) then Tablel.GotoBookmark(bml); if Tablel.BookmarkValid(bml) then Tablel.FreeBookmark(bml); Tablel.EnableControls; end;

Здесь для всех записей набора данных Tablel выполняется пересчет поля цены Price. Цены умножаются на коэффициент, который введен в редакторе Editl.

Метод Post вызывается автоматически при переходе к другой записи с помо­щью методов First, Last, Next и Prior, если набор данных находится в режи­ме редактирования, и изменения в записях не подтверждены. Поэтому в приве­денном примере метод Post можно было не вызывать, т. к. сразу после него вызывается метод Next. Однако при использовании методов FindFirst, FindLast, FindNext и FindPrior неподтвержденные изменения в записях бу­дут потеряны.

Пользователь подтверждает сделанные в записях изменения, управляя соответст­вующими компонентами, явно или неявно вызывающими метод Post. Конкрет-


Глава 7. Навигационный доступ к данным с помощью BDE


213


ные действия пользователя зависят от используемых компонентов. Например, при работе с компонентом DBGrid изменения подтверждаются (фиксируются) при пе­реходе к другой записи или нажатии клавиши <Enter>, а в компоненте DBNavigator можно нажать кнопку Post Edit (Подтвердить изменения).

Независимо от способа вызова, метод Post может завершиться неудачно, на­пример, если не заданы значения полей, которые не могут быть пустыми, или значение выходит за установленные для него допустимые пределы. В этом слу­чае набор данных обычно возвращается в состояние, которое было до перехода в режим редактирования. При ошибке выполнения метода Post генерируется со­бытие OnPostError типа TDataSetErrorEvent. Кодируя обработчик этого со­бытия, можно попытаться исправить ошибку.

Метод Cancel отменяет изменения, выполненные в текущей записи, и возвращает набор данных в режим просмотра. При выполнении метода Cancel вызываются обработчики событий BeforeCancel и AfterCancel типа TDataSetNotifyEvent.

Пользователь может отменить сделанные в записях изменения, используя эле­менты управления компонентов. Например, при работе с сеткой DBGrid изме­нения отменяются нажатием клавиши <Esc>, а в компоненте DBNavigator — нажатием кнопки Cancel Edit.

В случае применения механизма транзакций для отмены изменений сразу в не­скольких записях можно обратиться к методу RollBack класса TDateBase.

При редактировании текущей записи последовательность инструкций присваи­вания и вызовов метода Post можно заменить вызовом метода SetFields.

Процедура SetFields (const Values: array of const) устанавливает все или часть значений полей текущей записи. Параметр Values содержит массив значений, которые присваиваются этим полям, при этом порядок значений со­ответствует порядку полей в наборе данных. Кроме того, должны соответство­вать типы полей и типы присваиваемых им значений. Если значений в массиве меньше, чем полей в наборе данных, то эти значения присваиваются первым полям, а оставшиеся поля не изменяются. Чтобы не присваивать значение ка­кому-либо полю, в качестве соответствующего значения задается Nil, в резуль­тате поле не изменяется. Если число значений в массиве превышает число по­лей, то при выполнении метода SetFields генерируется исключение.

(_____ ЗамечаниеJ

Повторим еще раз, что значения Nil и Null не равны друг другу и имеют разный смысл. Nil означает отсутствие значения, a Null— пустое (нулевое) значение. Если вместо значения Nil указать значение Null, то поле будет изменено и со­держать значение Null.

Если для набора данных использовался Редактор полей, то при выполнении метода SetFields учитывается порядок полей, установленный с помощью этого Редакто­ра. В противном случае принимается порядок полей, определенный при создании таблицы БД.


214


Часть II. Технологии доступа к данным


Метод SetFields удобно использовать для изменения значений нескольких по­лей. После его выполнения набор данных автоматически возвращается в режим просмотра. Пример использования метода SetFields в программе:

Tablel.Edit;

Tablel.SetFields ([Nil, 'Иванов П.О.', Nil, 'Переводчик', 650]);

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

Добавление записей

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

Для добавления записи нужно выполнить следующие действия:

1. Перевести набор данных в режим вставки.

2. Задать значения полей новой записи.

3. Подтвердить сделанные изменения или отказаться от них, после чего набор данных снова переходит в режим просмотра.

Для добавления записей используются методы Insert, insertRecord, Append и AppendRecord.

Метод insert переводит набор данных в режим вставки и добавляет к нему но­вую пустую запись. Новая запись вставляется в позицию, на которой находится указатель текущей записи. При необходимости перед вызовом метода insert нужно выполнить перемещение текущего указателя в требуемую позицию набо­ра данных.

После перевода набора данных в режим вставки дальнейшие действия по зада­нию (изменению) значений полей, подтверждению или отмене сделанных изменений не отличаются от аналогичных действий при редактировании записи. При этом для задания или изменения значений полей используются инструкции присваивания и метод SetFields, а для подтверждения или отмены измене­ний — методы Post и Cancel. Некоторые поля новой записи могут остаться пустыми, если до подтверждения им не были присвоены значения.

(_____ ЗамечаниеJ

При переходе в режим вставки к набору данных добавляется пустая запись, значе­ния полей которой не заданы. Если запись добавляется к подчиненному набору данных, связанному с главным набором связью "главный-подчиненный", то индекс­ные поля автоматически получают корректные значения, и программист может не заботиться об их заполнении.

Рассмотрим следующий пример:

procedure TForml.ButtonlClick(Sender: TObject); begin


Глава 7. Навигационный доступ к данным с помощью BDE


215


Tablel.Insert;

Tablel.FieldByName('Name').AsString:= Editl.Text;

Tablel.FieldByName('Group').AsString:= Edit2.Text;

Tablel.Post;

end;

Здесь в новой записи задаются значения полей фамилии (Name) и группы (Group), остальные поля остаются пустыми. В этом и последующих примерах предполагается, что набор данных не связан с главным набором данных, и по­лям не были автоматически присвоены значения как индексным полям.

Часто удобно устанавливать значения сразу нескольких полей с помощью мето­да SetFields. Напомним, что после выполнения этого метода набор данных автоматически возвращается в режим просмотра, и запись считается включен­ной в набор данных. Если требуется изменить часть полей новой записи, то нужно использовать редактирование, а не вставку. Например, так:

procedure TForml.btnlnsertClick(Sender: TObject);

begin

if not Tablel.CanModifу then begin

MessageDlg('Записи изменять нельзя!', mtError, [mbOK], 0);

exit;

end;

Tablel.Insert;

Tablel.SetFields ([Nil, edtName.Text, Nil, edtPost.Text, IntToStr(edtCode.Text)]);

end;

Здесь значения полей новой записи пользователь вводит в редакторах. Первое и третье поля, а также поля с номером больше пяти остаются пустыми. Перед добав­лением записи выполняется проверка, можно ли изменять набор данных Tablel.

Метод insertRecord объединяет функциональность методов Insert и SetFields, выполняя те же действия, что и их последовательный вызов. Процедура InsertRecord (const Values: array of const) вставляет в позицию указа­теля текущей записи новую запись, задавая значения всех или части ее полей. Например:

procedure TForml.btnlnsertClick(Sender: TObject);

begin

Tablel.InsertRecord ([Nil, edtName.Text, Nil, edtPost.Text,

IntToStr(edtCode.Text)]); end;

Методы Append и AppendRecord отличаются от методов Insert и InsertRecord тем, что вставляют запись в конец набора данных, а не в позицию указателя текущей записи.


216


Часть II. Технологии доступа к данным


Пользователь управляет набором данных, в том числе вставкой записи, с помо­щью элементов управления формы. Для компонента DBGrid новая запись до­бавляется к набору данных при нажатии клавиши <Insert> или при переходе на последнюю запись. Если в форме находится компонент DBNavigator, то новая запись добавляется при нажатии кнопки Insert Record.

При добавлении новой записи любым методом возникают события

Beforelnsert и Afterlnsert типа TDataSetNotifyEvent, а также событие OnNewRecord типа TDataSetNotifyEvent. В обработчиках событий Beforelnsert и OnNewRecord можно выполнить действия, связанные с провер­кой набранных пользователем данных или с заполнением (инициализацией) части полей новой записи. Вот пример соответствующей процедуры:

procedure TForml.TablelNewRecord(DataSet: TDataSet);

begin

Tablel.FieldByName('Unit').AsString:= 'штука';

Tablel.FieldByName('NDS').AsString:= '20';

end;

При утверждении или отмене изменений, связанных с добавлением новой запи­си, также генерируются события BeforePost и AfterPost или BeforeCancel и AfterCancel.

Удаление записей

Удаление текущей записи выполняет метод Delete, который работает только с модифицируемым набором данных. В случае успешного удаления записи теку­щей становится следующая запись, если же удалялась последняя запись, то кур­сор перемещается на предыдущую запись, которая после удаления становится последней. В отличие от некоторых СУБД, в Delphi удаляемая запись действи­тельно удаляется из набора данных.

Обычно метод Delete вызывается для удаления просматриваемой записи, одна­ко с его помощью можно удалить и редактируемую запись. Если набор данных находится в режиме вставки или поиска, то вызов метода Delete аналогичен вызову метода Cancel, отменяя соответственно вставку или поиск записи.

(_____ ЗамечаниеJ

Если набор данных пуст, то вызов метода Delete порождает исключение.

При удалении записи генерируются события BeforeDelete и AfterDelete ти­па TDataSetNotifyEvent. Используя обработчик события BeforeDelete, мож­но отменить операцию удаления, если не соблюдаются определенные условия.

Если выполнение метода Delete приводит к ошибке, то возбуждается исклю­чение, и генерируется событие OnDeleteError, в обработчике которого можно


Глава 7. Навигационный доступ к данным с помощью BDE


217


выполнить собственный анализ ошибки. Вот небольшая процедура, в которой перед удалением записи запрашивается подтверждение пользователя:

procedure TForial.btnDeleteClick(Sender: TObject);

begin

if MessageDlg('Удалить запись?',

reconfirmation, [mbYes, mbNo], 0) = mrYes then Tablel.Delete; end;

Удаление нескольких последовательно расположенных записей имеет особен­ность, связанную с тем, что при вызове метода Delete в цикле по перебору уда­ляемых записей не нужно вызывать методы, перемещающие указатель текущей записи. После удаления текущей записи указатель автоматически перемещается на соседнюю (обычно следующую) запись. Так можно удалить все записи набо­ра данных:

procedure TForml.btnDeleteAHClick(Sender: TObject);

var n: longint;

begin

Tablel.Last;

for n:= Tablel.RecordCount downto 1 do Tablel.Delete;

end;

В примере перебор записей выполняется с конца набора данных. После удале­ния текущей записи указатель снова оказывается на последней записи.

Для набора данных Table удалить все записи можно также с помощью метода EmptyTable, который вызывается в режиме исключительного доступа к таблице БД.

Перед удалением записи часто предварительно выполняется поиск записи (за­писей), удовлетворяющей заданным условиям. Для отбора группы удаляемых записей используется фильтрация. Метод Delete позволяет удалить записи, ви­димые в наборе данных. Поэтому с помощью фильтрации можно временно ос­тавить в наборе данных записи, которые подлежат удалению, а после удаления фильтрацию отключить.

Пример формы приложения

Обычно визуальные компоненты, предназначенные для редактирования, добав­ления и удаления записей, группируются на форме и работают взаимосвязанно. Вместе или рядом с этими компонентами часто располагают элементы управле­ния сортировкой, фильтрацией и поиском. Тем самым для пользователя обеспе­чивается удобство выполнения различных операций с данными.

Для примера рассмотрим форму (рис. 7.10), с помощью которой можно изме­нять записи таблицы, содержащей сведения о товарах. В информацию о товаре входят уникальный код записи (поле Code), название товара (поле Name), еди­ница измерения (поле Unit), цена единицы (поле Price) и примечание (поле


218


Часть II. Технологии доступа к данным


Note). Поле названия и поле цены товара обязательно должны быть заполнен­ными, поле кода — автоинкрементное, и его значение при добавлении новой записи формируется автоматически.



 


Рис. 7.10. Форма приложения для работы с товарами

Ниже приводится код модуля uChange формы Forml приложения.

unit uChange; interface


Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Db, DBTables, Grids, DBGrids, StdCtrls, Mask, DBCtrls, ExtCtrls;

type

DBGridl DataSourcel Tablel btnEdit cbCanEdit pnlChange Labell dbeName

TForml = class(TForm)

TDBGrid; TDataSource; TTable; TButton; TCheckBox; TPanel; TLabel; TDBEdit;


Глава 7. Навигационный доступ к данным с помощью BDE


219


 


dbePrice:

dbeNote:

Label2:

Label3:

Label4:

lblChangeKind:

btnChangeOK:

btnChangeCancel:

dbcbUnit:

btnClose:

lblRecordCount:

btnlnsert:

btnDelete:


TDBEdit;

TDBEdit;

TLabel;

TLabel;

TLabel;

TLabel;

TButton;

TButton;

TDBComboBox;

TButton;

TLabel;

TButton;

TButton;


procedure StateBrowse(Sender: TObject); procedure StateChange(Sender: TObject); procedure btnEditClick(Sender: TObject); procedure cbCanEditClick(Sender: TObject); procedure TablelBeforeEdit(DataSet: TDataSet); procedure btnCloseClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure btnChangeOKClick(Sender: TObject); procedure btnChangeCancelClick(Sender: TObject) procedure btnDeleteClick(Sender: TObject); procedure btnlnsertClick(Sender: TObject); procedure TablelBeforePost(DataSet: TDataSet); procedure TablelBeforelnsert(DataSet: TDataSet)

private

{ Private declarations } public

{ Public declarations }

end;

Forml: TForml; implementation {$R *.DFM}

// Режим просмотра

procedure TForml.StateBrowse(Sender: TObject);


220


Часть II. Технологии доступа к данным


 


= False; = False; = clBlack; = 'ПРОСМОТР ЗАПИСИ'

begin

lblRecordCount.Caption:= 'Всего записей ToStr(Tablel.RecordCount);

cbCanEditClick(Sender); btnChangeOK.Enabled btnChangeCancel.Enabled lblChangeKind.Font.Color lblChangeKind.Caption end;


+ Int-


 


// Режимы изменения

procedure TForml.StateChange(Sender: begin

btnEdit.Enabled:= False;

btnlnsert.Enabled:= False;

btnDelete.Enabled:= False;

btnChangeOK.Enabled:= True;

btnChangeCancel.Enabled:= True;
end;


TObject)


procedure TForml.FormCreate(Sender: TObject); begin

// Исходное состояние элементов управления StateBrowse(Sender);

// Первоначально изменение записей запрещено cbCanEdit.Checked:= False;

// Запрет автоматического перехода в режим редактирования DataSourcel.AutoEdit:= False; // Формирование списка единиц измерения товара dbcbUnit.Items.Clear; dbcbUnit.Items.Add('шт.'); dbcbUnit.Items.Add('упак.'); dbcbUnit.Items.Add('кор.'); end;

procedure TForml.cbCanEditClick(Sender: TObject);

var bml: TBookmark;

begin

// Запоминание положения текущей записи

bml:= Tablel.GetBookmark;

// Отключение отображения изменений данных в визуальных компонентах

Tablel.DisableControls;

if not cbCanEdit.Checked then begin


Глава 7. Навигационный доступ к данным с помощью BDE


221


Tablel.Active:= False;

Tablel.Readonly:= True;

Tablel.Active:= True;

// Блокирование элементов, связанных с переходом

// в режимы изменения записей

btnEdit.Enabled:= False;

btnlnsert.Enabled:= False;

btnDelete.Enabled:= False;

end

else begin

Tablel.Active:= False;

Tablel.Readonly:= False;

Tablel.Active: = True;

// Разблокирование элементов, связанных с переходом

// в режимы изменения записей

btnEdit.Enabled:= True;

btnlnsert.Enabled:= True;

// Если набор данных пуст, то удаление записей запрещено

if Tablel.RecordCount > О

then btnDelete.Enabled:= True else btnDelete.Enabled:= False;

end; // Возврат к текущей записи

if Tablel.BookmarkValid(bml) then Tablel.GotoBookmark(bml); if Tablel.BookmarkValid(bml) then Tablel.FreeBookmark(bml); // Включение отображения изменений данных в визуальных компонентах Tablel.EnableControls;

end;

procedure TForml.TablelBeforeEdit(DataSet: TDataSet);

begin

// Запрос на подтверждение перехода в режим редактирования

if MessageDlg('Будете редактировать?',

mtConfirmation, [mbYes, mbNo], 0) о mrYes then Abort; end;

// Переход в режим редактирования

procedure TForml.btnEditClick(Sender: TObject);

begin

Tablel.Edit;

lblChangeKind.Font.Color:= clRed;

lblChangeKind.Caption:= 'РЕДАКТИРОВАНИЕ ЗАПИСИ';


222


Часть II. Технологии доступа к данным


StateChange(Sender);

if dbeName.CanFocus then dbeName.SetFocus; end;

procedure TForml.TablelBeforelnsert(DataSet: TDataSet);

begin

// Подтверждение перехода в режим вставки

if MessageDlg('Добавить запись?',

mtConfirmation, [mbYes, mbNo], 0) <> mrYes then Abort; end;

// Переход в режим вставки

procedure TForml.btnlnsertClick(Sender: TObject); begin

Tablel.Insert;

lblChangeKind.Font.Color:= clBlue; lblChangeKind.Caption:= 'ВСТАВКА ЗАПИСИ'; StateChange(Sender);

if dbeName.CanFocus then dbeName.SetFocus; end;

// Переход в режим просмотра удаляемой записи

procedure TForml.btnDeleteClick(Sender: TObject);

begin

// Подтверждение перехода в режим просмотра удаляемой записи

if MessageDlg('Удалить запись?',

mtConfirmation, [mbYes, mbNo], 0) о mrYes then Exit; lblChangeKind.Font.Color:= clRed; lblChangeKind.Caption:= 'УДАЛЕНИЕ ЗАПИСИ'; StateChange(Sender);

if btnChangeCancel.CanFocus then btnChangeCancel.SetFocus; end;

procedure TForml.TablelBeforePost(DataSet: TDataSet);

begin

// Проверка, задано ли значение для названия товара

if dbeName.Text = '' then begin

Beep;

MessageDlg('He задано название товара!', mtError, [mbOK], 0);

if dbeName.CanFocus then dbeName.SetFocus;

Abort;

end; // Проверка, задано ли значение цены товара if dbePrice.Text = '' then begin


Глава 7. Навигационный доступ к данным с помощью BDE


223


Веер;

MessageDlg('Не задана цена товара!', mtError, [mbOK], 0);

if dbePrice.CanFocus then dbePrice.SetFocus;

Abort;

end;

end;

procedure TForial.btnChangeOKClick(Sender: TObject);

begin

// Утверждение изменений в текущей записи (редактируемой или новой)

// или удаления текущей записи (просматриваемой)

if Tablel.State in [dsEdit, dslnsert]

then Tablel.Post

else if lblChangeKind.Caption = 'УДАЛЕНИЕ ЗАПИСИ' then Tablel.Delete; StateBrowse(Sender);

end;

procedure TFo rial.btnChangeCancelClick(Sender: TObject); begin

// Если набор данных находился в режиме просмотра (при удалении записи), // то никаких действий метод Cancel не выполняет Tablel.Cancel; StateBrowse(Sender); end;

// Закрытие формы

procedure TFonal.btnCloseClick(Sender: TObject); begin Close; end;

end.

В качестве набора данных используется компонент Tablel, записи которого отображает сетка DBGridl. Значения полей текущей записи отображаются в компонентах edtName, dbcbUnit, edtPrice и edtNote. Установка свойств, оп­ределяющих взаимные отношения компонентов, связанных с набором данных, выполнена при разработке приложения через Инспектор объектов.

Пользователь не может переводить набор данных в режимы изменения с помо­щью визуальных компонентов, т. к. свойство AutoEdit источника данных DataSourcel установлено в значение False.

Для перевода набора данных в режимы редактирования и вставки служат кноп­ки Изменить (btnEdit) и Добавить (btninsert) соответственно. Переход в эти режимы осуществляется вызовом методов Edit и insert, после чего название


224


Часть II. Технологии доступа к данным


режима отображается в надписи lblChangeKind, блокируются кнопки, связан­ные с переходом в режимы изменения, и разблокируются кнопки btnChangeOK и btnChangeCancel, позволяющие принять или отменить изменения, сделанные при редактировании или вставке записи. Для подтверждения или отмены изменений вызываются методы Post или Cancel, после чего кнопки подтверждения снова блокируются, а кнопки перехода в режимы изменения разблокируются. Изменение и задание значений полей выполняются с помощью компонентов edtName, dbcbUnit, edtPrice и edtNote.

При переходе в режимы, связанные с изменением записей, пользователю пред­лагается подтвердить свои действия, что программируется в обработчиках собы­тий OnBeforeEdit и OnBeforelnsert.

Программирование удаления записей отличается от предыдущих действий по изменению набора данных, т. к. режим удаления у набора данных отсутствует. При нажатии кнопки Удалить (btnDelete) набор данных остается в режиме просмотра текущей записи. Однако надпись lblChangeKind указывает на пере­ход в режим удаления, и если пользователь подтвердит удаление, нажав кнопку btnChangeOK, то для удаления текущей записи вызывается метод Delete. Таким образом, понятие "режим удаления" относится к форме, а не к набору данных. Запрос на подтверждение перехода в режим удаления кодируется в обработчике события нажатия кнопки btnDelete.

Флажок cbCanEdit с заголовком Редактирование разрешено включает и отклю­чает возможность изменения в наборе данных. Управление этой возможностью осуществляется через свойство Readonly набора данных. Свойство переключа­ется только при закрытом наборе данных. После нового открытия набора дан­ных указатель текущей записи устанавливается на первую запись, поэтому перед переключением свойства Readonly положение указателя текущей записи запо­минается с помощью закладки, а после переключения это положение восста­навливается. При разрешении изменений в наборе данных проверяется число его записей, и если набор данных пуст, то кнопка btnDelete блокируется.

Работа со связанными таблицами

Между отдельными таблицами БД может существовать связь, которая организу­ется через поля связи таблиц. Поля связи обязательно должны быть индексиро­ванными. Связь между таблицами определяет отношение подчиненности, при котором одна таблица является главной, а вторая — подчиненной. Обычно ис­пользуется связь "один-ко-многим", когда одной записи в главной таблице мо­жет соответствовать несколько записей в подчиненной таблице. Такая связь так­же называется "мастер-детальный" (Master-Detail). После установления связи между таблицами при перемещении в главной таблице текущего указателя на какую-либо запись в подчиненной таблице автоматически становятся доступ­ными записи, у которых значение поля связи равно значению поля связи теку­щей записи главной таблицы. Такой отбор записей подчиненной таблицы явля­ется своего рода фильтрацией.


Глава 7. Навигационный доступ к данным с помощью BDE



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: