A WinForms DataGridView control has the ability to automatically generate its columns and populate from a specified data source (which can be a DataSet, a simple list or something else). All you have to do is something like this:
var list = new List<Record>() {new Record() {Id = 1, Name = "item 1", Date = DateTime.Now}}; this.dataGridView.AutoGenerateColumns = true; this.dataGridView.DataSource = list;
When you do the same in MFC, it doesn’t work (supposing that you followed all the steps for hosting a WinForms control in an MFC application as described in MSDN).
m_dgv->AutoGenerateColumns = true; auto source = gcnew System::Collections::Generic::List<Record^>(); auto r1 = gcnew Record(); r1->Id = 1; r1->Name = "item 1"; r1->Date = System::DateTime::Now; source->Add(r1); m_dgv->DataSource = source;
After debugging through the .NET framework sources I realized the problem was that the BindingContext property of the DataGridView control was null. This property represents a manager of the list of bindings for the control. If this is null then the control will use the binding context of the parent, which is usually a WinForms form. However, in this MFC application there is no WinForms form and the parent of the DataGridView control is null, which means the control does not have a bindings manager, and no bindings can be set.
The solution is to explicitly set the BindingsContext property to an existing binding context (a new object) before setting the data source.
m_dgv->BindingContext = gcnew System::Windows::Forms::BindingContext(); m_dgv->DataSource = source;
The lesson learned is that when you host a WinForms control in an MFC application some things won’t just work out of the box, if they rely on a parent form functionality. There is no such WinForms form and you might need to do additional manual initialization.