Произвольный индекс для пунктов ComboBox
Модератор: Модераторы
- Nik
- энтузиаст
- Сообщения: 573
- Зарегистрирован: 03.02.2006 23:08:09
- Откуда: Киров
- Контактная информация:
Произвольный индекс для пунктов ComboBox
Пишу прогу, активно работающую с БД. Есть необходимость запросить у пользователя некие данные. Выбор осуществляется из списка, который - в свою очередь - заполняется каждый раз данными из БД. Нюанс такой: при заполнении списка удобно иметь под рукой не только текст (поле name), но и id каждого пункта (для упрощения проверок и записи обратно в БД). Но в ComboBox id не засунешь. Удобнее всего было бы использовать StringGrid и писать id в отдельный столбец, но таблица слишком громоздка и неудобна. Пока придумал только извращение с комбинацией TEdit и StringGrid.
Может кто-то сталкивался с подобным. Какие ещё есть варианты?
Может кто-то сталкивался с подобным. Какие ещё есть варианты?
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Пример, cbDivision - обычный ComboBox
Более развернуто, код очень древний
Здесь заполняем
А вот здесь извлекаем из комбобокса
PS: Невнимательно прочел, но что мешает в
в качестве первого параметра взять строку не из таблицы, а сформировать свою - id + табулятор (для ровного отступа) + значение (name) из таблицы
Код: Выделить всё
repeat
cbDivisions.Items.AddObject(DM.IBqryUni.FieldByName('Name').AsString, TObject(DM.IBqryUni.FieldByName('uid').AsInteger));
DM.IBqryUni.Next;
until DM.IBqryUni.Eof;Более развернуто, код очень древний
Здесь заполняем
Код: Выделить всё
procedure TfmRefEmployees.FormCreate(Sender: TObject);
begin
inherited;
cbDivisions.Items.Clear;
DM.IBqryUni.Close;
DM.IBqryUni.SQL.Text := 'select * from refdivisions where flag = 1 order by name';
DM.IBqryUni.Open;
repeat
cbDivisions.Items.AddObject(DM.IBqryUni.FieldByName('Name').AsString, TObject(DM.IBqryUni.FieldByName('uid').AsInteger));
DM.IBqryUni.Next;
until DM.IBqryUni.Eof;
cbDivisions.Items.InsertObject(0, '< ВСЕ >', nil);
cbDivisions.ItemIndex := 0;
DM.IBqryUni.Close;
end;А вот здесь извлекаем из комбобокса
Код: Выделить всё
procedure TfmRefEmployees.cbDivisionsClick(Sender: TObject);
var
Obj: TObject;
S: string;
Bookmark: Integer;
begin
inherited;
if Sender is TComboBox then begin
Bookmark := DM.IBqryEmployees.FieldByName('uid').AsInteger;
S := 'select * from refemployees';
if Assigned(TComboBox(Sender).Items.Objects[TComboBox(Sender).ItemIndex]) then begin
Obj := TComboBox(Sender).Items.Objects[TComboBox(Sender).ItemIndex];
S := Format('%s where idrefdivisions = %d', [S, Integer(Obj)]);
end;
if not cbShowDischarged.Checked then begin
if Pos('where idrefdivisions', S) > 0 then
S := S + ' and resigned = 0'
else
S := S + ' where resigned = 0';
end;
S := S + ' order by surname, name, middle';
dsReference.Dataset.Close;
TIBQuery(dsReference.Dataset).Transaction.Active := False;
TIBQuery(dsReference.Dataset).SQL.Text := S;
dsReference.Dataset.Open;
TIBQuery(dsReference.Dataset).FetchAll;
TIBQuery(dsReference.Dataset).Transaction.Active := True;
DM.IBqryEmployees.Locate('uid', Bookmark, [loPartialKey]);
end;
end;PS: Невнимательно прочел, но что мешает в
Код: Выделить всё
cbDivisions.Items.AddObject(DM.IBqryUni.FieldByName('Name').AsString, TObject(DM.IBqryUni.FieldByName('uid').AsInteger));в качестве первого параметра взять строку не из таблицы, а сформировать свою - id + табулятор (для ровного отступа) + значение (name) из таблицы
стандартный вариант - делать выбор из грида, привязанного к таблице, из которой грузятся данные в комбо, в каком-то модальном окне. соответственно id-ник берётся из самой таблицы без всяких танцев с бубном.
второй вариант, характерный для комбобоксов и прочих. у всех потомков TStrings кроме свойства Items есть полезное свойство Values. если сказать комбобоксу ComboBox1.Items.Add ('RecNo=100');, то:
1. ComboBox1.Items.Names [0] = 'RecNo';
2. ComboBox1.Items.Values ['RecNo'] = '100';
3. ComboBox1.Items.ValueFromIndex [0] = '100';
и т.д.
поэтому иногда в комбобоксах, листбоксах и прочих щастливых обладателях свойства Items: TStrings имеет смысл использовать добавлять значения в виде ('Name=Value'), а потом просто пеорехватывать отрисовку (для комбобокса - свойство Style ставим в csOwnerDrawFixed, а в обработчике OnDrawItem пишем свой код, выводящий на экран только значения Items.Names. но у этого подхода есть существенный недостаток: если в Names содержится знак равно, строка будет распарсена неправильно.
и третий вариант.
при создании формы мы якобы добавляем объект, а на деле присваиваем указателю нужное нам значение, а потом - просто вытаскиваем его оттуда.
второй вариант, характерный для комбобоксов и прочих. у всех потомков TStrings кроме свойства Items есть полезное свойство Values. если сказать комбобоксу ComboBox1.Items.Add ('RecNo=100');, то:
1. ComboBox1.Items.Names [0] = 'RecNo';
2. ComboBox1.Items.Values ['RecNo'] = '100';
3. ComboBox1.Items.ValueFromIndex [0] = '100';
и т.д.
поэтому иногда в комбобоксах, листбоксах и прочих щастливых обладателях свойства Items: TStrings имеет смысл использовать добавлять значения в виде ('Name=Value'), а потом просто пеорехватывать отрисовку (для комбобокса - свойство Style ставим в csOwnerDrawFixed, а в обработчике OnDrawItem пишем свой код, выводящий на экран только значения Items.Names. но у этого подхода есть существенный недостаток: если в Names содержится знак равно, строка будет распарсена неправильно.
и третий вариант.
- это не так. в TStrings можно запихивать не только строки, но и объекты (см. свойство TStrings.Objects). и это очень часто и очень широко используется, потому что указатель на объект - это longint, 8-разрядное целое, в которое можно запихать практически любой идентификатор либо ссылку на оный. и делаеться это очень просто:Но в ComboBox id не засунешь
Код: Выделить всё
procedure TForm1.FormCreate(Sender: TObject);
var
i: integer;
begin
for i := 1 to 10 do
ComboBox1.Items.AddObject(IntToStr (i), TObject (i));
end;
procedure TForm1.ComboBox1CloseUp(Sender: TObject);
begin
ShowMessage (IntToStr (integer (ComboBox1.Items.Objects [ComboBox1.ItemIndex])));
end;при создании формы мы якобы добавляем объект, а на деле присваиваем указателю нужное нам значение, а потом - просто вытаскиваем его оттуда.
yurgel писал(а):указатель на объект - это longint, 8-разрядное целое
32-разрядное (4-байтное) беззнаковое целое на 32-битных платформах и 64-разрядное (8-байтное) - на 64-битных.
Поэтому компилятор будет не доволен
Зачем такие сложности можно просто взять связанные динамические массивы...
- Nik
- энтузиаст
- Сообщения: 573
- Зарегистрирован: 03.02.2006 23:08:09
- Откуда: Киров
- Контактная информация:
Лишняя память + необходимость тройной синхронизации данных между интерфейсной частью, БД и промежуточным массивом (использовал в одном из старых проектов подобный подход - очень неудобно). ComboBox есть в любом случае, так что логичнее привязать всё к нему. А никакой особой сложности в методе с ComboBox1.Items.AddObject, который предложил yurgel, я не вижу (собственно, уже применил его на практике - всё отлично работает
)
v-t-l писал(а):yurgel писал(а):указатель на объект - это longint, 8-разрядное целое
32-разрядное (4-байтное) беззнаковое целое на 32-битных платформах и 64-разрядное (8-байтное) - на 64-битных.
Поэтому компилятор будет не доволен
с разрядностью я перегнул, каюсь
