Once you set up the proper data-access components, you can build a user interface to let a user view the data and eventually edit it. Delphi provides many components that resemble the usual controls but are data-aware. For example, the DBEdit component is similar to the Edit component, and the DBCheckBox component corresponds to the CheckBox component. You can find all these components in the Data Controls page of the Delphi Component Palette.
All these components are connected to a data source using the corresponding property, DataSource. Some of them relate to the entire dataset, such as the DBGrid and DBNavigator components, and the others refer to a specific field of the data source, as indicated by the DataField property. Once you select the DataSource property, the DataField property editor will contain a list of available values.
Notice that all the data-aware components are unrelated to the data-access technology, provided the data-access component inherits from TDataSet. Thus your investment in the user interface is preserved when you change the data-access technology. However, some of the lookup components and extended use of the DBGrid (displaying a lot of data) make sense only when you're working with local data and should generally be avoided in a client/server situation, as you'll see in Chapter 14.
The DBGrid is a grid capable of displaying a whole table at once. It allows scrolling and navigation, and you can edit the grid's contents. It is an extension of the other Delphi grid controls.
You can customize the DBGrid by setting its Options property's various flags and modifying its Columns collection. The grid allows a user to navigate the data using the scrollbars and perform all the major actions. A user can edit the data directly, insert a new record in a given position by pressing the Insert key, append a new record at the end by going to the last record and pressing the Down arrow key, and delete the current record by pressing Ctrl+Del.
The Columns property is a collection from which you can choose the table fields you want to see in the grid and set column and title properties (color, font, width, alignment, caption, and so on) for each field. Some of the more advanced properties, such as ButtonStyle and DropDownRows, can be used to provide custom editors for a grid's cells or a drop-down list of values (indicated in the column's PickList property).
DBNavigator is a collection of buttons used to navigate and perform actions on the database. You can disable some of the DBNavigator control's buttons by removing some of the elements of the VisibleButtons set property.
The buttons perform basic actions on the connected dataset, so you can easily replace them with your own toolbar, particularly if you use an ActionList component with the predefined database actions provided by Delphi. In this case, you get all the standard behaviors, but you'll also see the various buttons enabled only when their action is legitimate. The advantages of using the actions is that you can display the buttons in the layout you prefer, intermix them with other buttons of the application, and use multiple client controls, including main and popup menus.
There are multiple text-oriented components:
To let a user choose a value in a predefined list (which reduces input errors), you can use many different components. DBListBox, DBComboBox, and DBRadioGroup are similar, providing a list of strings in the Items property, but they do have some differences:
The DBCheckBox component is slightly different; it is used to show and toggle an option, corresponding to a Boolean field. It is a limited list because it has only two possible values plus the undetermined state for fields with null values. You can determine which are the values to send back to the database by setting the ValueChecked and ValueUnchecked properties of this component.
The DbAware Example
The DbAware example highlights the usage of a DBRadioGroup control with the settings discussed in the previous section and a DBCheckBox control. This example is not much more complex than earlier ones, but it has a form with field-oriented data-aware controls, instead of a grid encompassing them all. You can see the example's form at design time in Figure 13.3.
As in the MyBase2 program, the application defines its own table structure, using the FieldDefs collection property of the ClientDataSet. Table 13.1 provides a short summary of the fields defined.
The program has some code to fill in the table with random values. This code is tedious and not too complex, so I won't discuss the details here, but you can look at the DbAware source code if you are interested.
If the list of values is extracted from another dataset, then instead of the DBListBox and DBComboBox controls you should use the specific DBLookupListBox or DBLookupComboBox component. These components are used every time you want to select for a field a value that corresponds to a record of another dataset (and not to choose a different record to display!).
For example, if you build a standard form for taking orders, the orders dataset will generally have a field hosting a number indicating the customer who made the order. Working directly with the customer number is not the most natural way; most users will prefer to work with customer names. However, in the database, the customers' names are stored in a different table, to avoid duplicating the customer data for each order by the same customer. To get around such a situation, with local databases or small lookup tables, you can use a DBLookupComboBox control. (This technique doesn't port well to client/server architecture with large lookup tables, as discussed in the next chapter.)
The DBLookupComboBox component can be connected to two data sources at the same time: one source containing the data and a second containing the display data. I built a standard form using the orders.cds file from the Delphi sample data folder; the form includes several DBEdit controls.
You should remove the standard DBEdit component connected to the customer number and replace it with a DBLookupComboBox component (and a DBText component, to fully understand what is going on). The lookup component (and the DBText) is connected to the DataSource for the order and to the CustNo field. To let the lookup component show the information extracted from another file (customer.cds) you need to add another ClientDataSet component referring to the file, along with a new data source.
For the program to work, you need to set several properties of the DBLookupComboBox1 component. Here is a list of the relevant values:
object DBLookupComboBox1: TDBLookupComboBox DataField = 'CustNo' DataSource = DataSourceOrders KeyField = 'CustNo' ListField = 'Company;CustNo' ListSource = DataSourceCustomer DropDownWidth = 300 end
The first two properties determine the main connection, as usual. The next four properties determine the field used for the join (KeyField), the information to display (ListField), and the secondary source (ListSource). In addition to entering the name of a single field, you can provide multiple fields, as I did in the example. Only the first field is displayed as combo box text, but if you set a large value for the DropDownWidth property, the combo box's drop-down list will include multiple columns of data. You can see this output in Figure 13.4.
Figure 13.4: The output of the CustLookup example, with the DBLookupCombo-Box showing multiple fields in its drop-down list
Delphi includes a graphical data-aware control: DBImage. It is an extension of an Image component that shows a picture stored in a BLOB field, provided the database uses a graphic format that the Image component supports, such as BMP or JPEG (if you add the JPEG unit to your uses clause).
Once you have a table that includes a BLOB storing an image with a compatible graphic format, hooking it to the component is trivial. If, instead, the graphic format requires a custom transformation in order to be displayed, it might be easier to use a standard non-data-aware Image component and write code so the image is updated each time the current record changes. Before I can discuss this subject, however, you need to know more about the TDataSet class and the dataset field classes.
|Copyright © 2004-2021 "Delphi Sources" by BrokenByte Software. Delphi Programming Guide||