Анонимные методы для заполнения заголовков таблиц
Опубликовано 09.10.2011 г. 22:31
Часто ли вам приходится настраивать таблицу TStringGrid и ей подобные в коде? В моей работе, например, часто бывают такие ситуации. На форме размещен одна таблица TStringGrid, и несколько кнопок действий. Каждая кнопка по своему заполняет таблицу. В итоге в каждом методе обработчике нажатия кнопки приходится писать в основном одинаковый код для установки размеров таблицы и заполнения заголовков строк и столбцов.
Конечно можно решать эту проблему разными способами. Можно вообще не решать и в каждом обработчике нажатия кнопки менять таблицу. Можно, например, добавить метод заполнения таблицы вида:
procedure FillHeaders(sender : TObject); var c,r : integer; begin if Sender = Button1 then begin myGrid.colCount := 5; myGRid.rowCount := 10; for i := 0 to 4 do myGrid.Cells[i, 0] := 'col' + IntToStr(i); end; if Sender = Button2 then begin ..... end; end;Ну или можно завести отдельный метод для заполнения каждой из таблиц. Мне вот недавно почему то придумался вариант с использованием анонимных методов. Функционал по установке числа строк столбцов и непосредственно назначения заголовков можно вынести в отдельный клаcс/запись. В итоге от нас потребуется только пара методов получения заголовка по его индексу для строки и столбца. Для работы можно создать запись использующую классовые переменные и методы:
TGridHeaders = record strict private class var FGrid : TStringGrid; public type THeaderProc = reference to function(const index : integer): string; class procedure Update(const colCount, rowCount : integer; ColProc : THeaderProc = nil; RowProc : THeaderProc = nil); static; class procedure Clear(); static; class property Grid : TStringGrid read FGrid write FGrid; end;Запись имеет классовое свойство Grid и соответствующую переменную член класса. Сигнатура анонимного метода вынесена в отдельный тип - THeaderProc. Для обновления состояния таблицы используется метод Update:
class procedure TGridHeaders.Update(const colCount, rowCount: integer; ColProc : THeaderProc = nil; RowProc : THeaderProc = nil); var c,r : integer; begin if not assigned(FGrid) then exit; try FGrid.ColCount := colCount; FGrid.RowCount := rowCount; for c := 0 to colCount - 1 do begin if assigned(ColProc) then FGrid.Cells[c,0] := colProc(c) else FGrid.Cells[c,0] := IntToStr(c); end; for r := 1 to rowCount - 1 do begin if assigned(RowProc) then FGrid.Cells[0,r] := RowProc(r) else FGrid.Cells[0,r] := IntToStr(r); end; except raise; end; end;Метод имеет только два обязательных параметра - количество строк и столбцов, да и то, возможно они не требуются. Для заполнения заголовков строк и столбцов и используются переданные анонимные методы. А в случае если они не переданы, то столбцы/строки просто нумеруются. Теперь в обработчиков нажатий кнопок нужно определить эти самые методы, если они, конечно, нужны, и вызвать метод обновления таблицы.
procedure TTestForm.Button1Click(Sender: TObject); var cp : TGridHeaders.THeaderProc; begin cp := function(const col : integer):string begin result := Format('Column %d', [col]); end; TGridHeaders.Update(10,10, cp); end;Данный метод устанавливает размеры таблицы в 10 строк и столбцов. Для заполнения заголовков столбцов используется определенная функция. Строки нумеруются по умолчанию.
procedure TTestForm.Button2Click(Sender: TObject); const rowsCount = 4; rowHeaders : array[0..rowsCount - 1] of string = ('','строка 1','стр. 2','стр.3'); var rp : TGridHeaders.THeaderProc; begin rp := function(const row :integer):string begin result := rowHeaders[row]; end; TGridHeaders.Update(10, rowsCount, function(const col : integer):string begin result := Char(Ord('A')+ col); end, rp); end;В этом методе заголовки строк определены в виде массива констант. Метод для заполнения строк задан в виде переменных, а для заполнения столбцов передается сразу в параметре вызова метода Update(). Конечно, о применимости данного способа для заполнения гридов можно поспорить. Скорее это просто вариант применения анонимных методов для подобных целей.
11.10.2011 в 08:06
11.10.2011 в 10:58
хочу уже давно сделать отдельный сайт, но что-то все времени на это не хватает