В данном посте будем осваивать способ подключения к БД по технологии DBExpress, некоторые Delphi компоненты доступа к базам данных (DataSource, DBGrid). Во многом, я пользовался книгой Д. Осипова Базы данных и Delphi.
Большая их часть находится на вкладке DataControls, за исключением компонента Data Source. Общая схема подключения, в самом простейшем случае, к БД в Delphi на основе технологии DBExpress выглядит таким образом.
Рис.1 Пример подключения к БД по технологии DBExpress
Компонент DataSource
Компонент Data Source – посредник между компонентами – наборами данных (TSimpleDataSet и TClientDataSet и др.) – с одной стороны и компонентами, которые непосредственно отображают / редактируют данные.
Какие ключевые свойства нужно настроить у DataSource?
Пожалуй единственное ключевое свойство только одно…
property DataSet:TDataSet;
Доступно как в дизайн-тайм, так и в ран-тайм. В дизайн-тайм – предоставит все возможные в проекте датасеты (в примере на рис.1 – предоставит единственный DataSet).
Что ещё можно узнать от компонента DataSource?
Проверить связан ли компонент с набором данных поможет функция
function DataSource1.IsLinkedTo(DataSet:TDataSet):boolean;
property AutoEdit:Boolean;
По умолчанию – в режиме true – автоматический перевод в режим редактирования, связанного с DataSource компонента-набора данных. Можно также воспользоваться процедурой DataSource.edit;
При любом изменении данных (переводе курсора, модификации и др.) вызывается процедура
property OnDataChange:TDataChangeEvent;
Если меняется набор связанных данных, то это отражается в свойстве
property OnStateChange:TNotifyEvent;
Перед передачей в базу модификаций, сделанных пользователем, происходит обработка в
property OnUpdateData(TNotifyEvent);
Общие принципы подключения компонентов DataControls
У всех компонентов нужно указать свойство
property DataSource:TDataSource;
У компонентов, работающих с единственным полем таблицы БД (TDBText,TDBEdit,TDBMemo) необходимо настроить свойство
property DataField:TDataField;
Если компонент способен не только отображать, но и редактировать данные, то их можно поставить в режим Readonly
property Readonly:Boolean;
Индивидуальные свойства компонентов DataControls
Очень хорошо описаны в книге Д.Осипова – Базы данных и Delphi.
Компонент TDBGrid
Наиболее сильный и мощный компонент TDBGrid – по сути это таблица, отражающая таблицу из БД. Чтобы умело пользоваться компонентами DataControls, предлагаю главный из них – TDBGrid – разобрать подробно.
property Fields[index:integer]:TField;
Одно из важнейших свойств. Когда мы подключаем таблицу, компонент узнает о передаваемых ему полях, и, в дальнейшем, мы можем обращаться к нему напрямую.
property FieldCount:integer;
Это просто счетчик полей.
User кликнул на ячейку, как узнать колонку, поле соответствующее выбранной ячейке?
property SelectedField:TField;
property SelectedIndex:integer;
Эти свойства доступны для чтения / записи. Это значит, что можно выбирать ту или иную колонку для записи / просмотра данных программно.
Также есть группа свойств, сосредоточенных в свойстве
property Options:TDBGridOptions;
TDBGridOptions:set of TDBGridOption;
Ниже я привожу отрывок из книги Д.Осипова Базы данных и Delphi
Следующая теоретическая информация из книги Д.Осипова Базы данных и Delphi.
Одновременный выбор нескольких строк
Если в опциях сетки включены флаги dgMultiSelect и dgRowSelect, разрешающие одновременный выбор двух и более строк, то массив отмеченных пользователем строк окажется в свойстве компонента TDBGrid:
property SelectedRows: TBookmarkList; //только для чтения
Свойство предоставляет доступ к специальному объекту, экземпляру класса
TBookmarkList, хранящему список закладок (с закладками мы уже встречались во
время изучения класса TDataSet) .
Общее число строк, выбранных пользователем в сетке, окажется в свойстве
Property Count : integer;
Доступ к отдельному элементу списка закладок обеспечивается благодаря
свойству:
property Items[Index: Integer]: TBookmark;
Параметр Index определяет порядковый номер строки в массиве.
Обратную задачу (по содержимому закладки выяснить ее индекс в массиве)
решает метод
function IndexOf(const Item: TBookmark): Integer;
Если в списке закладок элемент Item обнаружен не был, то функция вернет
значение -1.
Аналогичного результата можно достичь, обратившись к методу
function Find(const Item: TBookmark; var Index: Integer): Boolean;
Функция проверяет, входит ли закладка Item в список, если закладка обнаружена, то метод порадует нас значением true. Номер закладки в массиве записывается в формальный параметр Index.
Для проверки, входит ли текущая запись в перечень отмеченных пользователем
строк, следует обратиться к свойству списка закладок
property CurrentRowSelected: Boolean;
Если строка выделена, то свойство вернет true, в обратном случае false. Поле
CurrentRowSelected несет не только информационную нагрузку, с помощью этого
свойства мы можем помечать строки программным образом.
Обновление списка закладок с удалением поврежденных элементов (например,
когда запись физически удалена из набора данных, а ссылающаяся на нее закладка
все еще “болтается” в памяти) реализуется методом
function Refresh: Boolean;
Очистку всего списка закладок осуществит метод
procedure Clear;
В результате вызова процедуры со всех строк сетки снимается признак выделе-
ния и инициируется процедура перерисовки ее клиентской области.
И, наконец, последний и самый опасный метод класса TBookmarkList. Он обес-
печивает физическое удаление выбранных в сетке записей из связанного с ней набора данных TDataSet:
procedure Delete;
Колонки сетки
По умолчанию в момент подключения компонента TDBGrid к активному набору
данных в сетке создаются колонки. Количество колонок определяется числом доступных полей набора данных — каждому полю сопоставляется своя колонка. Порядок следования колонок в точности соответствует порядку столбцов, определенных в наборе данных. Если колонки создавались автоматически, то их называют динамическими. Вместе с тем, существует и другой способ создания колонок. Программист обладает правом определить перечень требуемых ему колонок, как во время проектирования (для этого в Delphi реализован специальный редактор), так и непосредственно в коде приложения. Колонки, созданные “вручную”, именуют
статическими.
Доступ ко всем колонкам компонента TDBGrid предоставляется с помощью
свойства
property Columns: TDBGridColumns;
которое направит нас к коллекции колонок элемента управления.
Коллекция колонок — класс TDBGridColumns
Класс TDBGridColumns называют коллекцией колонок. поскольку он является
непосредственным наследником коллекции TCollection — специализированного
класса, ориентированного на хранение объектов различного типа.
Общее число колонок, находящихся в контейнере, узнается благодаря свойству
property Count: Integer; //только для чтения
Доступ к отдельному элементу коллекции реализуется уже знакомым нам спо-
собом. Необходимо указать порядковый номер элемента в списке:
property Items[Index: Integer]: TColumn default;
Возможные значения Index ограничены диапазоном от 0 до Count-1.
Как уже упоминалось ранее, колонки могут создаваться автоматически систе-
мой, так и руками разработчика.
Для выяснения способа создания предназначено
специальное свойство коллекции колонок:
type TDBGridColumnsState = (csDefault, csCustomized);
property State: TDBGridColumnsState;
Значение csDefault свидетельствует о том, что коллекция заполнилась дина-
мически, csCustomized — здесь поработал программист.
Ссылка на компонент-сетку, которой принадлежат колонки, находится в свой-
стве
property Grid: TCustomDBGrid; //только для чтения
Методы класса TDBGridColumns, в первую очередь, нацелены на манипуляции с
колонками, содержащимися в коллекции.
Создание новой колонки обеспечивается функцией
function Add: TColumn;
Новый экземпляр TColumn добавляется в конец списка.
Два метода решают вопросы сохранения информации об атрибутах колонок в
файл или память:
procedure SaveToFile(const Filename: string); //сохранить в файл
procedure SaveToStream(S: TStream); //сохранить в память
Задача загрузки данных из файла или памяти решается с помощью другой пары
процедур:
procedure LoadFromFile(const Filename: string); //загрузить из файла
procedure LoadFromStream(S: TStream); //загрузить из памяти
Колонка — класс TColumn
Экземпляр колонки реализован на базе класса TColumn и содержится в коллек-
ции колонок сетки — свойстве Columns. Колонка располагает обширным набором
свойств и методов, к наиболее важным из которых стоит отнести свойства, отвечающие за взаимодействие с полем набора данных.
Колонка представляет интересы соответствующего столбца набора данных.
Поэтому она обладает знаниями о физическом имени этого поля:
property FieldName: String;
Более того, в колонке хранится ссылка на соответствующий ей объект-поле:
property Field: TField;
При необходимости допустимо запретить редактирование отдельной колонки
сетки:
property ReadOnly: Boolean;
Каждая колонка снабжена заголовком — ячейкой, размещенной в самом верх-
нем ряду фиксированной области сетки. Для настройки внешнего вида заголовка
необходимо обратиться к свойству
property Title: TColumnTitle;
Настройки DBGrid по умолчанию
Для полного возврата к настройкам по умолчанию вызовите процедуру
procedure RestoreDefaults;
Другие свойства и методы колонок
procedure Assign(Source: TPersistent); override; копирует колонку Source в текущую колонку.
По умолчанию в заголовке колонки отображается содержимое свойства DisplayLabel объекта TField, к которому подключена эта колонка.
Для изменения значения по умолчанию воспользуйтесь свойством
property DisplayName: String;
Подстановка текстовых данных через PickList;
Если колонка ассоциирует обычное текстовое поле, предназначенное для хра-
нения сравнительно небольшого перечня данных, то целесообразно объединить
возможные варианты допустимых значений в единый список и обеспечить пользователя механизмом выбора нужного значения из этого списка. Для решения такой
задачи столбец TColumn обладает свойством
property PickList: TStrings;
Программист обладает возможностью ограничить число строк, выпадающих из
справочного листа, при помощи свойства
property DropDownRows: Cardinal;
При выборе пользователем ячейки, обладающей справочным листом, в правой
ее части появляется кнопка, щелчок по которой инициирует выпадение списка. Ко-
лонка разрешает определить порядок показа этой кнопки. Для этого реализовано
свойство:
type TColumnButtonStyle = (cbsAuto, cbsEllipsis, cbsNone);
property ButtonStyle: TColumnButtonStyle;
По умолчанию свойство установлено в значение cbsAuto — автоматическое
включение кнопки при наличии в колонке справочного листа или если колонка
связана с полем синхронного просмотра. При выборе значения cbsEllipsis с ячей-
кой ассоциируется кнопка с многоточием на поверхности, щелчок по кнопке вызы-
вает событие OnEditButtonClick() . Значение cbsNone — отказ от показа кнопки.
Ряд свойств колонки нацелен на обслуживание полей, состоящих из нескольких
дочерних полей. Признак того, что колонка взаимодействует с полями такого ти-
па — значение true, возвращаемое информационным свойством
property Expandable: Boolean;//только для чтения
Чтобы развернуть составную колонку и отобразить все дочерние поля, устано-
вите в true свойство
property Expanded: Boolean;
Обратная операция скроет дочерние поля.
Количество непосредственных предков колонки возвратит метод
function Depth: Integer;
Если родительских колонок нет — ответом станет нулевое значение.
Если родительская колонка все-таки существует, то ссылка вносится в свойство
property ParentColumn: TColumn;
Если составная колонка видима (visible=true) и не отображает дочерних колонок (expanded=false), то в свойстве
property Showing: Boolean;
окажется значение false.
С колонкой может быть связано свое собственное всплывающее меню
property PopupMenu: TPopupMenu;
Колонка знает, какой сетке она принадлежит:
property Grid: TCustomDBGrid;
Если с колонкой сетки связан вложенный набор данных, то, вызвав метод компонента TDBGrid,
procedure ShowPopupEditor(Column: TColumn;
X: Integer = Low(Integer); Y: Integer = Low(Integer)); dynamic;
мы сможем показать его в отдельном окне. Здесь Column — ссылка на колонку; X
и Y — экранные координаты левого верхнего угла всплывающего окна.
Обработка событий
На этом данный пост закончу. В остальных – компоненты для отдельных полей БД из палитры DataControls IDE Delphi.