Редактор видимости полей грида своими руками
Автор Administrator   
11.03.2009 г.

Автор: voldan, Королевство Delphi

Сегодня хотелось бы предложить Вам на обсуждение довольно интересную тему под названием "Возможность редактировать видимость полей грида", отвечающую всего-лишь двум условиям : видимо (Visible = True) и скрыто (Visible = False). И к данной теме прилагаю собственный компонент TFldSetting, который способен ускорить ту рутину, с которой нам всем приходится встречаться.

Конечно же, многие программисты имеют в своем арсенале нечто подобное, разработанное ими же или сторонними разработчиками. Но как же быть начинающему программисту или программисту, который не задумывался о возможности предоставлять пользователю (для которого и пишется, собственно, приложение) возможность добавлять-удалять колонки грида? Ведь он тоже хочет качественное приложение, способное удовлетворить как и заказчика, так и самого программиста. Поправлюсь, добавлять-удалять колонки - это действие (иллюзия) со стороны пользователя, а со стороны программиста, конечно же, это просто производить "редактирование видимости полей сетки", т.е. просто скрывать и показывать эти поля, не более того.

Немного об истории названия компонента "Редактор видимости полей". Дело в том, что я долго думал, как же лучше русскими словами можно охарактеризовать данный компонент. Были идеи назвать его "Видим-невидим", "Невидимка", "Кое-что еще про видимость" : , но всё это как-то не особо вязалось на языке. И одним утром, придя на работу, меня осенило: "Редактор видимости полей грида"!!! Это замечательное название повергло в шок определенных сотрудников, когда я у них спросил: "Как вам такой вариант редактора видимости полей грида"? :) Они спросили, что, Дань, опять чё-та выдумываешь? А я говорю: "Да нет же! Это обычный "Редактор видимости полей грида"! Вот так и появилось это замечательное название :)

У каждой сетки (почти у каждой) есть свойство Columns, которое открывает нам доступ к объектам-столбцам класса TColumn. Почему я сказал почти у каждой, потому что есть некоторые сетки(например, TcxGrid, грид, который входит в комплектацию библиотеки DevExpress), у которых доступ к столбцам осуществляется немного по-другому. Сторонние компоненты в данной статье я рассматривать не буду, потому что ориентируюсь на большинство как начинающих программистов, так и опытных гуру, которые пользуются стандартными компонентами. Хочу поправиться, некоторые сторонние компоненты (например, TDBGridEh из библиотеки EhLib) имеют много общего со стандартным TDBGrid, что в 100-процентном случае подходит для работы с данным компонентом. На самом деле, я сам работаю исключительно с TDBGridEh, и в самом начале компонент был "заточен" именно под него. Пришлось для вас немного модернизировать компонент, чтобы он работал под стандартным TDBGrid. Поверьте, ничего здесь сложного нет, если кто-то захочет перевести работу компонента под другие сетки. Естественно, если захочется, можно приспособить работу компонента к разным гридам методом "простого перечисления", но, чтобы не усложнять код лишними модификациями, я посчитал лишним это действие.

Но это всё касается самого грида. Многие товарищи работают напосредственно с наборами данных, добавляя и удаляя поля, присваивая им названия, имена, проставляя видимость и так далее. Данный компонент к таким товарищам не относится, потому что он работает исключительно по колумнам грида. Дело вот в чем. Программист, заливший поля в сам набор, лишается замечательной возможности использовать интересные вещи объектов-столбцов. Я в данной статье не буду обсуждать, что лучше, а что хуже, это мы сможем обсудить и на форуме, но скажу одно - до поры до времени я и сам пользовался заливкой полей в сам набор данных, но очень терял в другом. Я уже говорил, что пользуюсь TDBGridEh, так вот, возможности столбцов в данном гриде намного превосходят возможности стандартного TDBGrid. Опять же, перечислять их не буду, кому интересно, могут сами оценить.

Если приложение разрабатывается для одного пользователя, то, по большому счету, программист может один раз настроить видимость полей и забыть про это. Но существуют серьезные приложения, с которыми приходится работать множеству пользователей, у которых есть свои права доступа, определенные привилегии по работе с данными и так далее. И каждому такому пользователю необходимо видеть, подчеркиваю, СВОИ "колонки данных". Например, одному пользователю необходимо видеть в справочнике сотрудников "Пол сотрудника", а другому это абсолютно не важно. Так давайте дадим возможность пользователям самим решать, что они хотят видеть, а что нет?

Для начала, давайте определимся со спецификой задачи.

  1. При определенном событии происходит вызов формы компонента, в которой перечисляются поля грида.
  2. Пользователь методом установки флажка в чекбоксах (работаем с TCheckListBox) настраивает видимость полей
  3. При нажатии на кнопку "Сохранить" настройки сохраняются, а при нажатии "Отмена" - происходит откат всего того, что было выставлено.

Вот, в принципе, и все бабушкины огурчики, как я люблю говорить :)

А теперь давайте окунемся в детали, с которыми нам предстоит разобраться.

Если программист захотел не светить поле(я) в редакторе, а в гриде светить, он проставляет у объекта-столбца Tag = -1. Вы скажите: Такого свойства нет у столбца TDBGrid! И будуте правы. Это свойство есть у TDBGridEh'го столбца. Поэтому, я в компоненте закомментарил обработку невидимых в редакторе полей. Кто хочет работать с TDBGridEh, на что, собственно, компонент и претендует - меняем все объявления переменных с TDBGrid на TDBGridEh и вместо DbGrids.pas подключаем DbGridEh.pas. Всего-то делов. Да, и не забываем раскомментарить обработку. Можно предусмотреть данную обработку и к обычному столбцу, но у него нестолько мало свойств, что не к чему даже привязаться.

И так, про детали мы тоже поговорили. Давайте, теперь, познакомимся ближе с нашим компонентом и его возможностями.

Основная рабочая нагрузка лежит в модуле формы (тот самый "редактор видимости"). Я решил не грузить сам компонент, а, как принято считать "хорошим тоном", грузить сам модуль формы, чтобы эта форма была самодостаточной и независимой ни от кого. Т.е. всю черную работу выполняет именно ее модуль, а сам компонент является, так сказать, прокладкой между редактором и конечным разработчиком. Разработчик задает компоненту необходимые входные данные, компонент эти данные передает модулю формы, модуль формы производит работу и на выходе мы получаем необходимый результат. Вот именно так и представляется работа.

Теперь о свойствах и методах:

Имеется 4 основных свойства:
  1. Grid - без комментариев
  2. IniFile - полный путь с именем файла *.ini, куда записывается вся информация по текущим настройкам всех датасетов приложения, с которыми оперирует наш компонент.
  3. Mode: TMenuMode = (fAutomatic, fManual);
      fAutomatic - автоматический режим компонента
      fManual - ручной режим компонента
  4. ShortCut - комбинация клавиш для вызова редактора
Имеется 2 метода:
  1. GetFieldsSettings - загрузка настроек полей из ini-файла
  2. ShowFieldsSettingForm - показ формы для настроек полей
О режиме fAutomatic.
Предполагается, что до вызова (включительно) события OnShow формы (на которой лежит грид), необходимый датасет уже открыт. Происходит подмена этого обработчика OnShow на новый с сохранением старого в переменную FOldShow: TNotifyEvent. И только при вызове деструктора нашего компонента старый обработчик возвращается форме. На самом деле Вы можете смело настроить так, как будет удобно, чтобы обработчик возвращался при других условиях и обстоятельствах, или вообще не возвращался, или вообще убрать автоматический режим компонента. Это всё зависит от конкретной специфики работа программиста, его устоев и привычки, от его профессионализма и опыта. Лично я (в основном, потому что задачи бывают разные) динамически открываю необходимые датасеты по событию OnShow данной формы. Некоторые настраивают активными датасеты в Design Time (что считаю абсолютно неправильным подходом). Но это не важно, т.к. данный материал написан не для того, чтобы учить хорошему тону программирования (этому можно поучиться на просторах Королевского форума), а предложить одну из реализаций настройки пользовательского интерфейса. При данном режиме, еще подменяется обработчик формы OnKeyDown, куда, собственно, и прописывается ShortCut.
О режиме fManual:
Программисту необходимо самому заботиться о загрузка настроек полей из ini-файла. Данное действие нужно осуществлять через метод GetFieldsSettings . А показ редактора самому вызывать по методу ShowFieldsSettingForm

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

Компонент и пример работы прилагается (см. Файловый архив::Файлы к статьям ).

  1. Компонент : модуль TFldSet.pas
  2. Форма: модули: FieldsSettingFrm.pas и FieldsSettingFrm.dfm
  3. Проект: Test
  4. База employee.db
Последнее обновление ( 11.03.2009 г. )