0
votes

I'm quite lost with something which is supposed to be simple.

I've got two DataSet, both containing two DataTable. Each DataTable is a list of Tables' name and Columns' names I'm reading from two databases' schemas.

I'm binding the tables' list DataTable to a DataGridView and the columns' list DataTable to a second DataGridView in master-detail mode. Everything is working fine for this first DataSet.

Then I'm adding two DataGridViewComboBoxColumn to each DataGridView and binding those columns' ComboBox to the second DataSet.

When you select a row from the master DataGridView, the detail DataGridView gets populated with the columns related to the selected row. However, the DataGridViewComboBoxColumn in the detail DataGridView only gets updated when the DataGridViewComboBoxColumn in the master DataGridView is selected.

Any idea how can I link the row selection in the master grid to the ComboBox?

I hope the question is clear enough, Thanks for the help!

using System;
using System.Data;
using System.Windows.Forms;

namespace MasterDetailTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private DataGridView dataGridView1 = new DataGridView();
        private DataSet dataSet1 = new DataSet();
        private BindingSource bindingSourceTables1 = new BindingSource();
        private BindingSource bindingSourceColumns1 = new BindingSource();

        private DataGridView dataGridView2 = new DataGridView();
        private DataSet dataSet2 = new DataSet();
        private BindingSource bindingSourceTables2 = new BindingSource();
        private BindingSource bindingSourceColumns2 = new BindingSource();


        private void Form1_Load(object sender, EventArgs e)
        {
            SetGrids(dataGridView1, dataGridView2);

            dataGridView1.DataSource = bindingSourceTables1;
            dataGridView2.DataSource = bindingSourceColumns1;

            // DataSet1
            DataTable tables1 = new DataTable("tables1");
            tables1.Columns.Add(new DataColumn("TABLE_NAME", typeof(string)));
            tables1.Columns.Add(new DataColumn("TABLE_NAME2", typeof(string))); //Map DataSet2's table name to DataSet1's table name

            DataTable columns1 = new DataTable("columns1");
            columns1.Columns.Add(new DataColumn("TABLE_NAME", typeof(string)));
            columns1.Columns.Add(new DataColumn("COLUMN_NAME", typeof(string)));
            columns1.Columns.Add(new DataColumn("COLUMN_NAME2", typeof(string)));   //Map DataSet2's column name to DataSet1's column name

            dataSet1.Tables.Add(tables1);
            dataSet1.Tables.Add(columns1);

            tables1.PrimaryKey = new DataColumn[] { tables1.Columns["TABLE_NAME"] };
            columns1.PrimaryKey = new DataColumn[] { columns1.Columns["TABLE_NAME"], columns1.Columns["COLUMN_NAME"] };

            dataSet1.Relations.Add(new DataRelation("TablesColumns", dataSet1.Tables["tables1"].Columns["TABLE_NAME"], dataSet1.Tables["columns1"].Columns["TABLE_NAME"]));

            bindingSourceTables1.DataSource = dataSet1;
            bindingSourceTables1.DataMember = "tables1";

            bindingSourceColumns1.DataSource = bindingSourceTables1;
            bindingSourceColumns1.DataMember = "TablesColumns";

            // DataSet2
            DataTable tables2 = new DataTable("tables2");
            tables2.Columns.Add(new DataColumn("TABLE_NAME2", typeof(string)));

            DataTable columns2 = new DataTable("columns2");
            columns2.Columns.Add(new DataColumn("TABLE_NAME", typeof(string)));
            columns2.Columns.Add(new DataColumn("COLUMN_NAME2", typeof(string)));

            dataSet2.Tables.Add(tables2);
            dataSet2.Tables.Add(columns2);

            tables2.PrimaryKey = new DataColumn[] { tables2.Columns["TABLE_NAME2"] };
            columns2.PrimaryKey = new DataColumn[] { columns2.Columns["TABLE_NAME"], columns2.Columns["COLUMN_NAME2"] };

            dataSet2.Relations.Add(new DataRelation("TablesColumns", dataSet2.Tables["tables2"].Columns["TABLE_NAME2"], dataSet2.Tables["columns2"].Columns["TABLE_NAME"]));

            bindingSourceTables2.DataSource = dataSet2;
            bindingSourceTables2.DataMember = "tables2";

            bindingSourceColumns2.DataSource = bindingSourceTables2;
            bindingSourceColumns2.DataMember = "TablesColumns";

            DataGridViewComboBoxColumn dccTables = new DataGridViewComboBoxColumn()
            {
                DataSource = bindingSourceTables2,
                DataPropertyName = "TABLE_NAME2",
                DisplayMember = "TABLE_NAME2",
                ValueMember = "TABLE_NAME2",
                HeaderText = "TABLE_NAME2",
                Name = "TABLE_NAME2"
            };

            dataGridView1.Columns.Remove("TABLE_NAME2");
            dataGridView1.Columns.Add(dccTables);

            DataGridViewComboBoxColumn dccColumns = new DataGridViewComboBoxColumn()
            {
                DataSource = bindingSourceColumns2,
                DataPropertyName = "COLUMN_NAME2",
                DisplayMember = "COLUMN_NAME2",
                ValueMember = "COLUMN_NAME2",
                HeaderText = "COLUMN_NAME2",
                Name = "COLUMN_NAME2"
            };

            dataGridView2.Columns.Remove("COLUMN_NAME2");
            dataGridView2.Columns.Add(dccColumns);

            //Data
            CreateData();

        }

        private void CreateData()
        {
            for (int i = 0; i < 3; i++)
            {
                DataRow dt = dataSet1.Tables["tables1"].NewRow();
                dt["TABLE_NAME"] = "TableName" + i;
                dataSet1.Tables["tables1"].Rows.Add(dt);

                for (int j = 0; j < 5; j++)
                {
                    DataRow dc = dataSet1.Tables["columns1"].NewRow();
                    dc["TABLE_NAME"] = "TableName" + i;
                    dc["COLUMN_NAME"] = "ColumnName" + i + j;
                    dataSet1.Tables["columns1"].Rows.Add(dc);
                }
            }
            for (int i = 0; i < 3; i++)
            {
                DataRow dt = dataSet2.Tables["tables2"].NewRow();
                dt["TABLE_NAME2"] = "TableName" + i;
                dataSet2.Tables["tables2"].Rows.Add(dt);

                for (int j = 0; j < 5; j++)
                {
                    DataRow dc = dataSet2.Tables["columns2"].NewRow();
                    dc["TABLE_NAME"] = "TableName" + i;
                    dc["COLUMN_NAME2"] = "ColumnName" + i + j;
                    dataSet2.Tables["columns2"].Rows.Add(dc);
                }
            }
        }

        private void SetGrids(DataGridView dgv1, DataGridView dgv2)
        {
            dgv1.Width = 400;
            dgv2.Width = 400;
            dgv2.Top = dgv1.Height;

            this.Controls.Add(dataGridView1);
            this.Controls.Add(dataGridView2);
        }

    }
}
1

1 Answers

0
votes

This issue has been bugging me for days and when I've finally asked the question... I've found the answer.

As expected the answer was easy. I've found inspiration in this article How to: Ensure Multiple Controls Bound to the Same Data Source Remain Synchronized

My solution was to add this code in the bindingSourceTables1's CurrentChanged event:

    private void bindingSourceTables1_CurrentChanged(object sender, EventArgs e)
    {
        bindingSourceTables2.Position = bindingSourceTables2.Find("TABLE_NAME2", ((DataRowView)((BindingSource)sender).Current).Row["TABLE_NAME2"]);
    }