C# Binding Source Control

2.1k views Asked by At

I am Developing a winforms application. I have two datagrid views populated from two different bindingsources(control). I am using these to implement the master detail approach. My problem is that when the first datagridview is populated using the binding source I can't select the first row of it ,because the first element in the binding source is defaultly selected and can't be selected. Can any one provide me a solution for this

1

There are 1 answers

5
Sebi On BEST ANSWER

As you say the first row is selected by default. So after populating the DataSource to your first GridView you can set the second GridView based on first entry. Later you check the selectionChanged Event to populate the second GridView based on selectedRow of your first one.

Code could look sth. like this:

private void PopulateDataSource()
{
    dataGridView1.DataSource = myBindingSource;

    DataRowView selectedRow;
    if (dataGridView1.SelectedRows.Count > 0)
        selectedRow = dataGridView1.SelectedRows[0] as DataRowView;

    if (selectedRow != null)
        dataGridView2.DataSource = myBindingSource2; //Set the BindingSource based on selectedRow in first Grid

}

private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
    DataRowView selectedRow;
    if (dataGridView1.SelectedRows.Count > 0)
        selectedRow = dataGridView1.SelectedRows[0] as DataRowView;

    if (selectedRow != null)
        dataGridView2.DataSource = myBindingSource2; //Set the BindingSource based on selectedRow in first Grid
}

If this doesn't work let me know but should do the job.

UDPATE

Here is a similar example using the events and methods of the bindingSource:

private void Initialize()
{
    RegisterBindingSourceEvents();
    dataGridView1.DataSource = bindingSource1;
    dataGridView2.DataSource = bindingSource2;
    bindingSource1.DataSource = myDataSource;
}

private void RegisterBindingSourceEvents()
{
    bindingSource1.DataSourceChanged += BindingSource1_DataSourceChanged;
    bindingSource1.CurrentChanged += BindingSource1_CurrentChanged;
}

private void BindingSource1_CurrentChanged(object sender, EventArgs e)
{
    DataRowView row = bindingSource1.Current as DataRowView;
    if (row != null)
        bindingSource2.DataSource = myDataSource2BasedOnRow;
}

private void BindingSource1_DataSourceChanged(object sender, EventArgs e)
{
    DataRowView row = bindingSource1.Current as DataRowView;
    if (row != null)
        bindingSource2.DataSource = myDataSource2BasedOnRow;
}

Further you maybe can use:

 bindingSource.MoveNext();
 bindingSource.MoveFirst();

To simulate focusing seconde row and directly first row. A bit ugly but i would guess this fires current_changed (untested). Better use first approach.

UDPATE-2

I'm sorry to tell you that this is not possible in a beautiful manner. The problem is that the Current Property of your bindingList is always set if your DataSource contains items. So if the user select the same row as the bindingSource Current Property contains your event won't get called. I found a solution which works in my example. You will need one gridEvent and maybe have to do some improvments but the idea should do the job. Sorry but without gridEvent i can't solve this:

Notice that iam using List as DataSource for my Testcase. You got DataTable and have to cast to DataRowView instead of Dummy for sure.

private bool _automatedRowChange;

        private void Initialize()
        {
            List<Dummy> dummies = new List<Dummy> { new Dummy { Id = 1, Text = "Test1" }, new Dummy { Id = 2, Text = "Test2" } };
            bindingSource1.DataSource = dummies;
            dataGridView1.DataSource = bindingSource1;

            //So the first row isn't focused but the bindingSource Current Property still holds the first entry
            //That's why it won't fire currentChange even if you click the first row. Just looks better for the user i guess
            dataGridView1.ClearSelection();

            bindingSource1.CurrentChanged += BindingSource1_CurrentChanged;
            dataGridView1.CellClick += DataGridView1_CellClick;
        }

        private void DataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            var clickedRow = dataGridView1.Rows[e.RowIndex].DataBoundItem as Dummy;
            var currentRow = bindingSource1.Current as Dummy;

            if (clickedRow != null &&
                currentRow != null &&
                clickedRow.Equals(currentRow))
            {
                _automatedRowChange = true;
                bindingSource1.MoveNext();

                _automatedRowChange = false; //MovePrevious is based on the click and should load the dataSource2
                bindingSource1.MovePrevious();
            }
        }

        private void BindingSource1_CurrentChanged(object sender, EventArgs e)
        {
            if (!_automatedRowChange) //Check if you jump to next item automatically so you don't load dataSource2 in this case
            {
                //Set the second DataSource based on selectedRow
            }
        }