0

I am trying to work around the problem described in this question. Basically I need the contents of a DataGridView to update when the underlying data are changed.

I am trying the 'data binding with an intermediate data source' approach (number three of the original options I outlined). To do this I have created a DataTable within the UI scope, which contains the same number of cells as the DataGridView. I then populate it with the relevant data and bind it to the DGV. This DataTable contains a subset of the underlying data, laid out as per the requirements of the user interface.

However, the DataTable does not update when the underlying data changes. I had tried to ensure that the table was populated with references rather than values, by specifying that the data type was 'object'. However, it seems that this doesn't work as I had hoped it might. Testing shows that the contents of the DataTable remain unchanged once entered. Presumably they are values.

To give a simplified example, say I have got a two-by-two DataGridView and want to populate it with the some basic statistics for a dog and a house, which form part of a much larger object model. What I am doing is something like this:

class Dog{
    string Name;
    int Age;
    float WeightInKG;
}
class House{
    string NameOrNumber;
    int YearBuilt;
    bool IsPainted;
}

Initialise the objects and create the data source, bound to the DGV:

DataTable dgvContents;
House thisHouse = new House();
Dog thisDog = new Dog();
InitObjects();
CreateDataTable();

private void InitObjects() {
    thisHouse.YearBuilt = 1970;
    thisHouse.IsPainted = true;
    thisDog.Name = "Spot";
    thisDog.Age = 3;
}
private void CreateDataTable() {
    dgvContents = populateDataTable();
    BindingSource SBind = new BindingSource();
    SBind.DataSource = dgvContents;
    dataGridView1.DataSource = SBind;
}
private DataTable PopulateDataTable() {
    DataTable thisTable = new DataTable("UITable");
    int cols = 2;
    int rows = 2;
    for (int i = 0; i < cols; i++)
    {
        thisTable.Columns.Add("", typeof(object));
    }
    for (int j = 0; j < rows; j++)
    {
        thisTable.Rows.Add(new object[cols]);
    }
    thisTable.Rows[0][0] = thisdog.Name;
    thisTable.Rows[0][1] = thisdog.Age;
    thisTable.Rows[1][0] = thisHouse.IsPainted;
    thisTable.Rows[1][1] = thisHouse.YearBuilt;
    return thisTable;
}

This method is only viable if the DataTable I am creating (dgvContents) contains references rather than values. Is this possible?

wotnot
  • 261
  • 1
  • 12
  • Do a Casting of the data source in the DataGridView var tbl=(DataTable)dgvContents.DataSource; – محمد النعيمي Jan 05 '20 at 22:16
  • I don't think that makes sense as written. dgvContents is already a DataTable, and doesn't have a DataSource property. – wotnot Jan 05 '20 at 22:29
  • 1
    I guess you probably meant var tbl = (DataTable)dataGridView1.DataSource, but I don't understand what I would do with 'tbl' having created it. – wotnot Jan 05 '20 at 22:40
  • Maybe you need [BindingSource.ResetBindings](https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.bindingsource.resetbindings?f1url=https%3A%2F%2Fmsdn.microsoft.com%2Fquery%2Fdev15.query%3FappId%3DDev15IDEF1%26l%3DEN-US%26k%3Dk(System.Windows.Forms.BindingSource.ResetBindings);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.7.2);k(DevLang-csharp)%26rd%3Dtrue&view=netframework-4.8) –  Jan 05 '20 at 23:44
  • Possibly I do. That has crossed my mind. But if I have to respond to PropertyChanged events doesn't that somewhat defeat the purpose of binding? – wotnot Jan 05 '20 at 23:46
  • Well mate, you have a `BindingSource` already. Use it to add/edit/remove items and call `EndEdit()` to update the underlying data source. If you need to change the data source then dispose the current BindingSource and create a new one and pass the data source, bind it to the DGV after `DGV.DataSource = null` –  Jan 05 '20 at 23:58
  • If I cannot use binding to create a lasting link between the data and the UI then binding seems pointless here. Responding to changes to the underlying data is problematic because it exists in classes remote from the UI, which does not receive Changed events. From what I am reading (e.g. https://stackoverflow.com/questions/11392894/bind-complex-object-to-cell-of-datatable-in-c-sharp) it seems that it may not really be possible to do any kind of complex binding to a DGV except with some tricky/hackish workaround solutions. – wotnot Jan 06 '20 at 00:37

0 Answers0