|
class CMyClass { public: CMyClass(double price, decimal quantity); ~CMyClass(); double GetPrice() const; void SetPrice(double price); long GetQuantity() const; void SetQuantity(long); private: double m_Price; long m_Quantity; };
This class has some public methods and private fields. Now, let's explain, how values, returned by the GetPrice() function can be shown in the grid. When you create a new object, the memory is allocated only for the values declared in this object (if there are no virtual functions). For the methods there is a memory allocation too, but the compiler does it the code segment. Each method can have its pointer. The declaration of the method pointer looks like
typedef double (CMyClass::*pfnGetDouble)() const;
double price = (object->*pfnGetDouble)();
Now, when there are the possibilities to call methods, let's add the notion of formats. The values, returned by the functions can't be presented directly in the grid. The values can have integer, float or other type. The grid can display only the strings. Indeed, the integer value 123456 can be presented in different way as '123456' or '0x1E240' etc. So the form of presentation depends on the format that can convert value to string. The Common library offers a number of formats to convert value to string and vice-versa. Each format may be bi-directional. When user types a string in the cell, the typing string can be parsed in the format and transformed to the value. Then this value can be passed to the SetPrice() function of your object.
The last step - is to explain how the function can be associated with the columns in the grid and what is the Field of the data object. Data object - is your own object of an arbitrary class. This class may have various Get- and Set- functions that manipulate of internal data of the object. The Get- and Set- functions can be grouped in the field. So the field is a pair of Get- and Set- functions with a format to transform the value to a string and vice-versa. The field has its own type (long, double etc). To identify the field we use numeric identifiers. Why? To avoid binding by strings that can lead to the late detected errors when we change identifier in one place and forget to do it in the second. Another reason, that numeric identifiers may be expressed by enumerations that is a good practice. So you can detect the errors at compilation time.
The Set- function of the field permits to transform string or data, received from edit in place controls (edit box, dropdown list etc:) to a value and pass it though described mechanism to the business object.
Now, the big question you can ask is the multithreading protection. Indeed, MFC controls can work only in a single thread. They are not thread-safe. Any call from any non-GUI thread can lead to the crash of the application. So, once you implemented notifications then the grid can receive them from any thread. There are many aspects of this problem:
Well, let's explain, how does it work. All functions of the Grid are thread-safe. They use two main algorithms: with or without blocking the calling thread. We don't want to say that calling of these functions in any thread is a best practice but only that the grid can work properly in case of such call. All functions that add, remove or get data, block the calling thread for the period of the operation. If you listen for some notifications from the grid, be aware that there is an implicit lock that holds the calling thread. Internally the grid doesn't call methods of your business data that can lead to the deadlock. So, be carefully in the notification handlers.
The data updating is performed without locking the calling thread. There is no risk of the deadlock, but it is up to you to protect your business data. We implemented two algorithms of data updating:
Now let's explain what is a Dapfor::Common::CDataObject: This is a base class for classes, the objects of which can be inserted in the grid. It implements described above binding mechanism and permits to call methods like GetPrice or SetPrice from the grid by their identifiers.
Supported types:
| definition | Type | Description |
| Common::StlString | std::string or std::wstring | STL string |
| Common::MfcString | CStrind | MFC string |
| Common::Char | char | 8-bit signed value |
| Common::UChar | unsigned char | 8-bit unsigned value |
| Common::Short | short | 16-bit signed value |
| Common::UShort | unsigned short | 16-bit unsigned value |
| Common::Long | long | 32-bit signed value |
| Common::ULong | unsigned long | 32-bit unsigned value |
| Common::Int64 | __int64 | 64-bit signed value |
| Common::Bool | bool | Boolean type |
| Common::Float | float | 32 bit value with a floating point |
| Common::Double | double | 64 bit value with a floating point |
| Common::ObjectPtr | Dapfor::Common::CDataObject* | Pointer to a data object |
| Common::Value | Dapfor::Common::CValue | Combination of the types described above |
Read How to install the MFC grid and compile the first application? article to get more information.
| Copyright Dapfor 2007-2009 | Generated on Sat Jan 30 15:01:23 2010 for MFCGrid by 1.5.5 |