Visual C++ DataGridView – data binding

DataGridView is a control introduced in .NET Framework version 2.0. displaying data in customizable grid.  The control can be used in any application developed on .NET Framework using any language (C++, C#, VB) based on CLR (Common Language Runtime).
The control can be customized through manipulating of DataGridView class properties. Some of them are: DefaultCellStyle, CellBorderStyle, GridColor, just to name a few.
That is the short introduction do DataGridView Control. However, what I would like to concentrate in this post is specifying a data source for the control. There are several ways introduced in MSDN documentation:

DataGridView::DataSource Property

What was needed to implement in an application was using as a datasource some collection of simple POCO’s (Plain Old C/C++ Object).

So going this way, a POCO is needed:

ref class StudentDataGridItem
{
    Int32^ _id;
    String^ _name1;
    String^ _name2;
    String^ _surname;  //leave more properties in sake of readibility
public:
    StudentDataGridItem(void);
    property int^ id     {       Int32 ^ get() {
        return _id;
    }       void set ( Int32^ value) {
        _id = value;
    }     }      property String^ name1     {       String^ get() {
        return _name1;
    }       void set ( String^ value) {
        _name1 = value;
    }     }      property String^ name2     {       String^ get() {
        return _name2;
    }       void set ( String^ value) {
        _name2 = value;
    }     }      property String^ surname     {       String^ get() {
        return _surname;
    }       void set ( String^ value) {
        _surname = value;
    }     }
};

The collection of objects of the above class is returned from a simple DAO:

ArrayList^ StudentsDAO::getStudents()
{
 Statement* stmt = conn->createStatement();
 ResultSet *res;
 ArrayList^ students = gcnew ArrayList();
 try{ 
  res = stmt -> executeQuery ("SELECT u.user_id as id, surname, name_1 as name1, name_2 as name2 FROM user u, student_extra s where u.user_id = s.user_id AND deleted = 0"); 
  
  while (res -> next()) {
   StudentDataGridItem^ student = gcnew StudentDataGridItem();
   student->id = res->getInt("id");
   student->surname= StringUtils::stdStringToSystemString(res->getString("surname"));
   student->name1 = StringUtils::stdStringToSystemString(res->getString("name1"));
   student->name2 = StringUtils::stdStringToSystemString(res->getString("name2"));

   students->Add(student);
  }
 }catch (SQLException &e) {
  //exception dealing logic
 }
 return students; 
}

and bound to DataGridViewControl:

this->studentsDataGridView->DataSource = (System::Object ^) studentsDAO.getStudents();

What is assumpted is that control has columns specified with DataPropertyName equal to the property from POCO from which value goes to the particular column.

As a result data grid with proper columns is displayed, hovewer it contains no data. DAO returns data, it is bound to grid’s data source but nothing is displayed. What is more, it works perfectly in C# and probably in VB (not tested by myself) but not in C++.

To make it work, Bindable (documentation: MSDN BindableAttribute Class) attribute is needed to be specified on each and every property which is bound to the data grid column. The proper POCO should look like this:

 ref class StudentDataGridItem
{ 
 Int32^ _id;
 String^ _name1;
 String^ _name2;
 String^ _surname;
 //leave more properties in sake of readibility
public:
 StudentDataGridItem(void);

    [System::ComponentModel::Bindable(true)]
    property int^ id
    {
      Int32 ^   get() { return _id; }
      void set ( Int32^ value) { _id = value; }
    }
    
    [System::ComponentModel::Bindable(true)]
    property String^ name1
    {
      String^   get() { return _name1; }
      void set ( String^ value) { _name = value; }
    }

    [System::ComponentModel::Bindable(true)]
    property String^ namee2
    {
      String^   get() { return _name2; }
      void set ( String^ value) { _name2 = value; }
    }

    [System::ComponentModel::Bindable(true)]
    property String^ surname
    {
      String^   get() { return _surname; }
      void set ( String^ value) { _surname = value; }
    }
};

Now, everything works properly and data grid displays data from the bound collection.

Leave a Reply

Your email address will not be published. Required fields are marked *