如何通过TextBox数组实现TextBox与DataGridView的绑定?多表场景下的代码简化及替代方案咨询
Got it, let's tackle this problem step by step. First, we'll fix your TextBox array implementation to properly handle the binding, then we'll explore other cleaner alternatives that can simplify this logic even more.
Fixing the TextBox/Control Array Approach
Your initial array attempt had a couple of issues—like incorrect array initialization and mixed-up loop variables. Since you're also using RichTextBox controls, we'll use a Control array instead to cover both control types. Here's a corrected, streamlined version:
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e) { // Exit if the user clicked the header row if (e.RowIndex < 0) return; DataGridViewRow selectedRow = dataGridView1.Rows[e.RowIndex]; Control[] boundControls = null; // Map the correct controls based on column count switch (dataGridView1.Columns.Count) { case 5: boundControls = new Control[] { textBox3, textBox4, textBox5, richTextBox1, richTextBox2 }; break; case 6: boundControls = new Control[] { textBox3, textBox4, textBox5, textBox6, richTextBox1, richTextBox2 }; break; default: // Fallback to your original default behavior boundControls = new Control[] { textBox3, textBox4 }; break; } // Loop through controls and assign cell values, handle nulls to avoid crashes for (int i = 0; i < Math.Min(boundControls.Length, selectedRow.Cells.Count); i++) { object cellValue = selectedRow.Cells[i].Value; boundControls[i].Text = cellValue?.ToString() ?? string.Empty; } }
Key improvements here:
- Uses a
Controlarray to support bothTextBoxandRichTextBox - Uses a
switchstatement to clearly map column counts to control sets - Adds null value handling to prevent
NullReferenceException - Uses
Math.Minto avoid index out-of-bounds errors if control count and column count don't match
Alternative Approaches to Simplify Binding
1. WinForms Built-In Data Binding (Recommended)
Manual cell click handling is unnecessary when you use WinForms' native data binding. This approach automatically syncs your controls with the DataGridView's selected row, and it supports two-way binding if you need to edit values and save them back to the data source.
Here's how to implement it:
// Example: Load 5-column table and set up bindings private void Load5ColumnTable() { DataTable your5ColumnTable = GetYour5ColumnData(); // Replace with your data fetch logic BindingSource bindingSource = new BindingSource(); bindingSource.DataSource = your5ColumnTable; // Bind DataGridView to the data source dataGridView1.DataSource = bindingSource; // Bind each control to the corresponding column (use your actual column names) textBox3.DataBindings.Add("Text", bindingSource, "FirstColumnName"); textBox4.DataBindings.Add("Text", bindingSource, "SecondColumnName"); textBox5.DataBindings.Add("Text", bindingSource, "ThirdColumnName"); richTextBox1.DataBindings.Add("Text", bindingSource, "FourthColumnName"); richTextBox2.DataBindings.Add("Text", bindingSource, "FifthColumnName"); // Clear bindings for controls not used in this table textBox6.DataBindings.Clear(); } // Example: Load 6-column table and set up bindings private void Load6ColumnTable() { DataTable your6ColumnTable = GetYour6ColumnData(); BindingSource bindingSource = new BindingSource(); bindingSource.DataSource = your6ColumnTable; dataGridView1.DataSource = bindingSource; textBox3.DataBindings.Add("Text", bindingSource, "FirstColumnName"); textBox4.DataBindings.Add("Text", bindingSource, "SecondColumnName"); textBox5.DataBindings.Add("Text", bindingSource, "ThirdColumnName"); textBox6.DataBindings.Add("Text", bindingSource, "FourthColumnName"); richTextBox1.DataBindings.Add("Text", bindingSource, "FifthColumnName"); richTextBox2.DataBindings.Add("Text", bindingSource, "SixthColumnName"); }
With this setup, selecting a row in the DataGridView will automatically update all bound controls—no need to write a CellClick event handler at all.
2. Dynamic Control Mapping
If your controls follow a consistent naming convention (e.g., textBox_FirstColumn, richTextBox_FourthColumn), you can dynamically find and bind controls without hardcoding arrays or binding lists. This is great for scalability if you add more tables or controls later.
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex < 0) return; DataGridViewRow selectedRow = dataGridView1.Rows[e.RowIndex]; foreach (DataGridViewCell cell in selectedRow.Cells) { // Look for a TextBox matching the column name first Control targetControl = this.Controls.Find($"textBox_{cell.OwningColumn.Name}", true) .FirstOrDefault() as Control; // If no TextBox found, check for a RichTextBox if (targetControl == null) { targetControl = this.Controls.Find($"richTextBox_{cell.OwningColumn.Name}", true) .FirstOrDefault() as Control; } // Assign value if we found a matching control if (targetControl != null) { targetControl.Text = cell.Value?.ToString() ?? string.Empty; } } }
This way, you don't need to update your code when adding new columns or controls—just keep the naming consistent.
内容的提问来源于stack exchange,提问作者rreskey

