Data binding
This page has been automatically translated using the Google Translate API services. We are working on improving texts. Thank you for your understanding and patience.
Data Binding is a technique that allows us to register the program structures or classes in order to automate certain tasks, such as synchronizing the data model with the user interface.
Functions
void | dbind (...) |
void | dbind_enum (...) |
type* | dbind_create (...) |
void | dbind_init (...) |
void | dbind_remove (...) |
void | dbind_destroy (...) |
void | dbind_destopt (...) |
type* | dbind_read (...) |
void | dbind_write (...) |
void | dbind_default (...) |
void | dbind_range (...) |
void | dbind_precision (...) |
void | dbind_increment (...) |
void | dbind_suffix (...) |
We understand by Data Binding the possibility of automatically synchronizing the structures of the program with different input/output sources. We start from the simple model (Listing 1) that we present in Arrays composed of a struct
and an enum
.
struct
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
The first thing we have to do is register this model in dbind, a kind of general "database" within our application (Listing 2). It is only necessary to carry out this process once when starting the program. In this way, internal tables will be created with the description of each structure of the data model (Figure 1), leaving the program ready to automate certain tasks when working with objects of said classes.
- Use dbind to register the fields of a structure.
- Use dbind_enum to register the different values of enum types.
1 2 3 4 5 6 7 8 9 |
dbind_enum(type_t, ekCPU, ""); dbind_enum(type_t, ekGPU, ""); dbind_enum(type_t, ekHDD, ""); dbind_enum(type_t, ekSCD, ""); dbind(Product, type_t, type); dbind(Product, String*, code); dbind(Product, String*, description); dbind(Product, Image*, image64); dbind(Product, real32_t, price); |
1. Synchronization with graphical interfaces
One of the most widespread uses of data binding is the possibility of synchronizing the graphical interface with the objects that make up the data model. This paradigm is known as MVVM (Model-View-ViewModel) (Figure 2)and we will delve deeper into it GUI Data binding.
2. Read and write JSON
The parsing of JSON scripts can also be automated thanks to dbind (Figure 3). In JSON you will have detailed information on how to do it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
{ "code":0, "size":80, "data":[ {"id":0, "code":"i7-8700K", "description":"Intel BX80684I78700K 8th Gen Core i7-8700K Processor", type":0, "price":374.8899999999999863575794734060764312744140625, "image":"cpu_00.jpg", "image64":"\/9j\/4AAQSkZJRgABAQ.... }, ... } |
3. Serialization with DBind
As we saw in Serialization and Unify serialization we need to define object reading and writing functions to send or receive them through streams. Fortunately, dbind knows the detailed composition of each registered object, so it's possible access the I/O without having to explicitly program these functions (Listing 3) (Figure 4).
1 2 3 |
ArrPt(Product) *products = dbind_read(stream, ArrPt(Product)); ... dbind_write(stream, products, ArrPt(Product)); |
4. Default constructor
Thanks to dbind we can also create objects initialized with default values without creating specific constructors (Listing 4). They can also be destroyed guaranteeing the correct recursive release of the memory of all their fields.
- Use dbind_create to create an object Constructors.
- Use dbind_init to initialize an object.
- Use dbind_destroy to destroy an object Destructors.
1 2 3 4 5 6 7 8 9 10 |
ArrSt(Product) *array = dbind_create(ArrSt(Product)); Product *pr1 = dbind_create(Product); Product *pr2 = arrst_new(array, Product); dbind_init(pr2, Product); // Use objects ... dbind_destroy(&pr1, Product); dbind_destroy(&array, ArrSt(Product)); |
The default values when initializing object fields are 0
for numbers, FALSE
for booleans, ""
for Strings and empty containers in the case of arrays or sets. If the object contains nested sub-objects, they will also be created/initialized recursively. These default values can be changed if necessary (Listing 5).
- Use dbind_default to set the default value.
1 2 3 4 |
dbind_default(Product, type_t, type, ekHDD); dbind_default(Product, String*, code, "Empty-code"); dbind_default(Product, real32_t, price, 5.f); dbind_default(Product, Image*, image64, gui_image(NOIMAGE_PNG)); |
5. Numerical ranges
It is possible to configure the numeric fields uint32_t, int8_t, real64_t, etc
to limit the accepted values (Listing 6). dbind will be responsible for validating the data every time it reads values from any data source (GUI, JSON, Streams, etc).
- Use dbind_range to set a maximum and minimum numerical values.
- Use dbind_precision to set numerical precision. For example
0.01
in monetary values. - Use dbind_increment to set the value of discrete increments.
- Use dbind_suffix to set a suffix that will be added when converting numbers to text.
price
value.
1 2 3 4 5 |
dbind_default(Product, real32_t, price, 10f); dbind_range(Product, real32_t, price, .50f, 10000f); dbind_precision(Product, real32_t, price, .01f); dbind_increment(Product, real32_t, price, 5.f); dbind_suffix(Product, real32_t, price, "€"); |
dbind ()
Adds a structure/class field to its internal table within dbind.
void
dbind(type,
mtype,
name);
type | Type of structure or class. |
mtype | Type of field to register. |
name | Name of the field within the structure. |
Remarks
Errors will be generated at compile time if the indicated field does not belong to the structure. The method also works for classes in C++.
dbind_enum ()
Register an enum
type value.
void dbind_enum(type, value, const char_t *alias);
type | Enum type. |
value | Value. |
alias | Alias para el valor. |
Remarks
dbind_enum(mode_t, ekIMAGE_ANALISYS, "Image Analisys");
it will use the string "Image Analisys" instead of "ekIMAGE_ANALISYS" for those I/O or interface operations that require displaying the literals of the enumeration. For example, to populate the fields of a PopUp linked with a data field.
dbind_create ()
Create an object of registered type, initializing its fields with the default values.
type* dbind_create(type);
type | Object type. |
Return
Newly created object or NULL
if dbind does not recognize the data type.
dbind_init ()
Initializes the fields of an object of a registered type with the default values.
void dbind_init(type *obj, type);
obj | Object whose memory has been reserved, but not initialized. |
type | Object type. |
dbind_remove ()
Destroys the memory reserved by the fields of an object of registered type, but does not destroy the object itself.
void dbind_remove(type *obj, type);
obj | Object. |
type | Object type. |
dbind_destroy ()
Destroy an object of registered type. The memory allocated to the fields and sub-objects will also be released recursively.
void dbind_destroy(type **obj, type);
obj | Object. Will be set to |
type | Object type. |
dbind_destopt ()
Destructor optional. Like dbind_destroy, but accepting NULL
values for the object.
void dbind_destopt(type **obj, type);
obj | Object to destroy. |
type | Object type. |
dbind_read ()
Creates an object of a registered type from the data read from a stream.
type* dbind_read(Stream *stm, type);
stm | Reading stream. |
type | Object type to read. |
Return
Newly created object or NULL
if there has been an error.
dbind_write ()
Write the content of an object of registered type in a write stream.
void dbind_write(Stream *stm, const type *data, type);
stm | Writing stream. |
data | Object to write. |
type | Type of object to write. |
dbind_default ()
Set the default value of a field.
void dbind_default(type, mtype, name, mtype value);
type | Type of structure or class. |
mtype | Field type. |
name | Name of the field within the structure. |
value | Default value as of now. |
dbind_range ()
Set the maximum and minimum value in numeric fields.
void dbind_range(type, mtype, name, mtype min, mtype max);
type | Type of structure or class. |
mtype | Field type. |
name | Name of the field within the structure. |
min | Minimum value. |
max | Maximum value. |
Remarks
It will fail if used in non-numeric fields.
dbind_precision ()
Set the jump between two consecutive numerical values.
void dbind_precision(type, mtype, name, mtype prec);
type | Type of structure or class. |
mtype | Field type. |
name | Name of the field within the structure. |
prec | Accuracy (eg |
Remarks
It will fail if used in non-numeric fields.
dbind_increment ()
Sets the increment of a numerical value when clicking on a UpDown control.
void dbind_increment(type, mtype, name, mtype incr);
type | Type of structure or class. |
mtype | Field type. |
name | Name of the field within the structure. |
incr | Increase. |
Remarks
It will fail if used in non-numeric fields.
dbind_suffix ()
Set a suffix that will be added to the numerical value when converted to text.
void dbind_suffix(type, mtype, name, const char_t *suffix);
type | Type of structure or class. |
mtype | Field type. |
name | Name of the field within the structure. |
suffix | Suffix. |
Remarks
It will fail if used in non-numeric fields.