C# DataGridView 和输入表单

C# DataGridView and Input Form

我有一个与数据库中的数据绑定的 DataGridView。我需要创建一个表单,其中包含来自单个网格行的数据的输入字段。 表单有 30 多个输入控件 - TextBoxes、Checkboxes 和 NumericUpDowns。

现在我采用了这种方法:

  1. 从 DataGridView 中检索当前行并将单元格中的值加载到 class 实例

  2. 将实例传递给表单并手动填充输入控件

  3. 从表单更新数据库,更新DataGridView

我想改进一些东西:

  1. 有没有什么方法可以从 class 实例中快速填充所有输入控件?
  2. 除了手动订阅事件处理程序上的每个控件之外,是否有任何方法可以确定哪些输入控件更改了它们的值?
  3. 有没有什么办法可以改善这一切,例如做事更有效率?

如果您已经传入 DataRow,那么您可以改为传入 DataTable 和标识该行的内容 table。如果您想在表单退出时立即提交更改,也可以选择一个适配器。然后您可以创建那个 table 的 DataView。并将每个编辑控件绑定到该视图中的一个字段。像这样:

public partial class EditForm : Form
{

    DataRow row = null;
    DataView view;
    SqlDataAdapter adapter;

    public EditForm(SqlDataAdapter adapter, DataTable table, int rowId)
    {
        InitializeComponent();

        this.adapter = adapter;

        view = table.DefaultView;
        view.RowFilter = $"ID = {rowId}";
        if (view.Count == 0) throw new Exception("no such row");
        DataRowView dvr = view[0];
        row = dvr.Row;

        datebox.DataBindings.Add(new Binding("Value", view, "DATE"));
        stringbox.DataBindings.Add(new Binding("Text", view, "O_STRING"));

        this.FormClosing += EditForm_FormClosing;
    }

    private void EditForm_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (row.RowState == DataRowState.Modified) adapter.Update(new DataRow[] { row });
    }
}

以上假设您的 table 具有名为 ID 的键列以及字段 DATEO_STRING.

这将为您省去创建中间自定义 class 实例的麻烦,基于该行,将值移入和移出各种对象并自动设置原始 table 中的 RowStatae。

回复:价值改变指标。不确定是否有真正优雅的方法来做到这一点。首先,如果必须的话,我会更改背景(或前景)颜色而不是字体粗体。将字体设置为粗体会改变内容的宽度,这通常很烦人。然后,我会将处理程序添加到 TextChanged 事件(或 ValueChange 事件,用于非基于文本的控件)。您不需要为每个编辑控件编写自定义处理程序 - 在事件处理程序中,您可以获得指向控件对象的 object sender 参数。然后你可以用这样的东西获得绑定到该控件的字段名称:

private void stringbox_TextChanged(object sender, EventArgs e)
{
    Control ctrl = (Control)sender;
    string fieldName = ctrl.DataBindings[0].BindingMemberInfo.BindingMember;
    if ((string)view[0].Row[fieldName] != ctrl.Text) ctrl.BackColor = Color.Pink;
}

这样您只需添加一次 TextChanged 处理程序(每个编辑控件 class),而不是每个编辑框都添加一个。