Todos ellos tienen un control homólogo estándar en la paleta de componentes. Se diferencian de los controles estándar en que están enlazados a datos (son componentes data-aware). Dicho enlace se establece mediante un DataSource.
Estos componentes trabajan con los datos seleccionados por las propiedades DataSource y, en su caso, DataField:
Propiedad | Descripción |
---|---|
DataSource | Indica el datasource del que se obtienen y al que se envían los datos. |
DataField | Es el campo o columna del datasource al que accede cada control. |
A continuación, presentaremos los distintos controles de datos del C++ Builder
Controles orientados a conjuntos de datos | |
Control | Descripción |
---|---|
TDBGrid | Rejilla de datos: Muestra un DataSource con aspecto de tabla. Mediante la propiedad Columns se pueden especificar qué campos del conjunto de datos se pueden ver en la rejilla y cuáles son sus propiedades. |
TDBCtrlGrid | Rejilla que permite incluir controles: Como un TDBGrid, aunque cada fila es en realidad un panel en el que se pueden colocar controles de datos "replicables". |
TDBNavigator | Control de navegación: Sirve para controlar el cursor, así como la inserción, edición y borrado de datos. La propiedad VisibleButtons se utiliza para seleccionar qué botones podrá pulsar el usuario. Por su parte, la propiedad Hints permite especificar mensajes de ayuda para cada botón (que habrá que traducir). |
TDBChart | Permite construir gráficos a partir de un conjunto de datos. La propiedad SeriesList se emplea para seleccionar qué datos deseamos representar y cómo |
Controles orientados a campos | |
Control | Descripción |
TDBText | Como el componente estándar TLabel, pero enlazado a datos. Muestra el valor de un campo, el cual no se puede editar. Igual que las etiquetas normales, no consume recursos en Windows. |
TDBEdit | Presenta un cuadro de edición para un campo concreto. Análogo a TEdit. |
TDBMemo | Caja de edición con múltiples líneas. Ideal para textos sin formato. |
TDBCheckBox | Se emplea en campos que sólo permiten dos valores diferentes. Con las propiedades ValueChecked y ValueUnchecked se establecen listas de valores para que el TDBCheckBox esté activado o desactivado. Dichas listas se especifican mediante una serie de valores separados por punto y coma. |
TDBRadioGroup | Se utiliza para campos que sólo permiten varios valores. En la propiedad Items se fijan los identificadores que el usuario ve en el grupo de botones. En la propiedad Values se indican los valores que en realidad se almacenan en la base de datos. |
TDBListBox | Establece una lista de posibles valores para un campo. En la propiedad Items se fijan los valores permitidos, que son fijos. |
TDBComboBox | TComboBox enlazado a datos. Igual que en el control TDBListBox, las distintas posibilidades se colocan en la propiedad Items. |
TDBLookupListBox | Ideal para claves externas: Como TDBListBox, aunque la lista de valores permitidos no la establece el programador. Los valores de la lista se obtienen a partir de los valores de un campo de otro conjunto de datos. El DataSource que se consulta se establece con la propiedad ListSource. El campo que se muestra en la lista de valores viene dado por la propiedad ListField. La propiedad KeyField indica el campo cuyos valores se almacenan en la base de datos. |
TDBLookupComboBox | Igual que TDBLookupListBox, aunque la lista aparece como un TComboBox. |
TDBRichEdit | Igual que TDBMemo, con la capacidad adicional de dar formato al texto del campo (en formato RTF). |
TDBImage | Para mostrar imágenes contenidas en una base de datos (en formato BMP o WMF). |
El comportamiento de todos los controles anteriores ante modificaciones se puede alterar con las propiedades AutoEdit y ReadOnly.
Se puede adaptar TDateTimePicker (página Win32 de la paleta de componentes) para que funcione con un TDataSource especificando sus eventos OnStateChange, OnDataChange y OnUpdateData. También es necesario personalizar el evento OnExit del componente TDateTimePicker.
Ejemplo |
class TFormDate : public TForm { ... private: bool FCambiando; ... }; void __fastcall TFormDate::DataSourceDataChange(TObject *Sender, TField *Field) { if (! FCambiando) try { FCambiando = True; DateTimePicker->DateTime = Table->FieldValues["HireDate"]; } __finally { FCambiando = False; } } void __fastcall TFormDate::DataSourceUpdateData(TObject *Sender) { Table->FieldValues["HireDate"] = DateTimePicker->DateTime; } void __fastcall TFormDate::DateTimePickerChange(TObject *Sender) { if (! FCambiando) try { FCambiando = True; DataSource->Edit(); } __finally { FCambiando = False; } } void __fastcall TFormDate::DateTimePickerExit(TObject *Sender) { Table->UpdateRecord(); } |
La tecla 'Insert' permite añadir tuplas, mientras que la combinación 'Control+Supr' se utiliza para eliminarlas. Por defectro, aparece un mensaje en inglés que se puede personalizar interceptando el evento BeforeDelete del conjunto de datos asociado:
Ejemplo de personalización de los mensajes mostrados al usuario |
void __fastcall ...::TableBeforeDelete(TDataSet *DataSet) { if ( MessageDlg ( "¿Desea eliminar la tupla actual?", mtConfirmation, TMsgDlgButtons()<<mbYes<<mbNo, 0) != mrYes ) Abort(); } |
Interceptando el evento OnDrawColumnCell se puede personalizar la presentación de las celdas: cambiar el color, el tipo de letra e incluso mostrar imágenes o checkboxes sin tener que recurrir al componente TDBCtrlGrid.
Personalización del color de un campo determinado (según el cumplimiento de alguna condición) |
void __fastcall TFormXXX::DBGridDrawColumnCell (TObject *Sender, const TRect Rect, int DataCol, TColumn *TColumn, TGridDrawState State) { TDBGrid *grid = static_cast<TDBGrid*>(Sender); if (tbParts->FieldValues["OnOrder"] >= tbParts->FieldValues["OnHand"]) grid->Canvas->Font->Color = clRed; grid->DefaultDrawColumnCell(Rect, DataCol, Column, State); } |
Propiedades del tipo de letra |
void __fastcall TFormXXX::DBGridDrawColumnCell (TObject *Sender, const TRect& Rect, int DataCol, TColumn *Column, TGridDrawState State) { TDBGrid *grid = static_cast<TDBGrid*>(Sender); TFontStyles FS; switch (grid->DataSource->DataSet->UpdateStatus()) { case usModified: FS << fsBold; break; case usInserted: FS << fsItalic; break; case usDeleted: FS << fsStrikeOut; break; } grid->Canvas->Font->Style = FS; grid->DefaultDrawColumnCell(Rect, DataCol, Column, State); } |
Imágenes en vez de texto |
void __fastcall TFormXXX::DBGridDrawColumnCell (TObject *Sender, const TRect Rect, int DataCol, TColumn *TColumn, TGridDrawState State) { TDBGrid *grid = static_cast<TDBGrid*>(Sender); if (Column->FieldName != "") grid->DefaultDrawColumnCell(Rect, DataCol, Column, State); else if (tbEmpleados->FieldValues["Salary"] >= 150000) grid->Canvas->StretchDraw(Rect, CaraAlegre->Picture->Graphic); else grid->Canvas->StretchDraw(Rect, CaraTriste->Picture->Graphic); } |
CheckBoxes (aunque es más cómodo y flexible utilizar TDBCtrlGrid) |
void __fastcall TFormXXX::DBGridDrawColumnCell (TObject *Sender, const TRect Rect, int DataCol, TColumn *TColumn, TGridDrawState State) { if (CompareText(Column->FieldName, "ACTIVO") == 0) { UINT check = 0; if (Table1->FieldValues["ACTIVO"]) check = DFCS_CHECKED; DBGrid->Canvas->FillRect(Rect); DrawFrameControl(DBGrid1->Canvas->Handle, (RECT*) &Rect, DFC_BUTTON, DFCS_BUTTONCHECK | check); } else DBGrid->DefaultDrawColumnCell(Rect, DataCol, Column, State); } |
Podemos seleccionar la columna por la que se ordenan los datos usando la propiedad IndexFieldNames del conjunto de datos. Esta propiedad la podemos establecer dinámicamente como respuesta al evento OnTitleClick.
Ordenación dinámica de un conjunto de datos |
void __fastcall TFormXXX::DBGridTitleClick(TColumn *Column) { try { if (Column->Field->FieldKind == fkLookup) Table->IndexFieldNames = Column->Field->KeyFields; else Table->IndexFieldNames = Column->FieldName; } catch(Exception&) { } } |
Append en vez de Insert |
void __fastcall TFormXXX::DBNavigatorBeforeAction(TObject *Sender,TNavigateBtn Button) { if (Button==nbInsert) { static_cast<TDBNavigator*>(Sender)->DataSource->DataSet->Append(); SysUtils::Abort(); } } |