Connor Connor - 2 months ago 14
C# Question

Update textbox by navigating DataGridView with arrow keys

public delegate void MyEventHandler(object sender, DataGridViewCellEventArgs e);
public event MyEventHandler SomethingHappened;

private void dataGridViewCargo_CellContentClick_1(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0)
{
DataGridViewRow rowID = this.dataGridViewCargo.Rows[e.RowIndex];
cargoDisplayMessageIdTextBox.Text = rowID.Cells["iDDataGridViewTextBoxColumn"].Value.ToString();

DataGridViewRow rowSender = this.dataGridViewCargo.Rows[e.RowIndex];
cargoDisplaySubjectTextBox.Text = rowSender.Cells["subjectDataGridViewTextBoxColumn"].Value.ToString();

}
}



protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
Invoke(new MyEventHandler(SomethingHappened));
return base.ProcessCmdKey(ref msg, keyData);
}


The first part updates my textbox's when I select the row. The second part is an attempt at an event handler. I want to to update the textboxes just by navigating the grid with keyboard. So whatever row is highlighted in blue automatically populates the textboxes.

I tried to invoke an event handler by including it in dataGridViewCargo_CellContentClick but sender and e don't pass through and I get Parameter Count Mismatch error or Delegate to an instance method cannot have null 'this'. The idea was to call the CellContentClick event by pressing a button.

Any help would be very kind.

Answer

When you use mouse or arrow keys to move between rows of your DataGridView is data-bound, the position of its data source changes and all controls which are bound to the same data source will show values from new position.

Also if you don't use data-binding the SelectionChanged event of DataGridView will be raised and can be used to update controls.

So you can use either of these options to solve the problem:

  • Bind those TextBox controls to the same data source which DataGridView uses.

  • Use SelectionChanged event of DataGridView.

If you bind DataGridView to a DataSource, then you can simply use data-binding for your TextBox controls too. It's enough to bind those TextBox controls to the fields of data source which you want to show by click on each row. You can perform data-binding using designer or using code:

var data = GetDataFromSomeShere();
dataGridViewCargo.DataSource = data;
cargoDisplayMessageIdTextBox.DataBindings.Add("Text", data, "ID");
cargoDisplaySubjectTextBox.DataBindings.Add("Text", data, "Subject");

If you don't use data-binding, you can simply use SelectionChanged event of DataGridView and use CurrentRow property of DataGridView to find those fields and update your TextBox control:

private void dataGridViewCargo_SelectionChanged(object sender, EventArgs e)
{
    var row = dataGridViewCargo.CurrentRow;
    cargoDisplayMessageIdTextBox.Text = 
        row.Cells["iDDataGridViewTextBoxColumn"].Value.ToString();
    cargoDisplaySubjectTextBox.Text =
        row .Cells["subjectDataGridViewTextBoxColumn"].Value.ToString();
}

Using data-binding (the first option) is preferred.