C# DataGridView 和输入表单
C# DataGridView and Input Form
我有一个与数据库中的数据绑定的 DataGridView。我需要创建一个表单,其中包含来自单个网格行的数据的输入字段。
表单有 30 多个输入控件 - TextBoxes、Checkboxes 和 NumericUpDowns。
现在我采用了这种方法:
从 DataGridView 中检索当前行并将单元格中的值加载到 class 实例
将实例传递给表单并手动填充输入控件
从表单更新数据库,更新DataGridView
我想改进一些东西:
- 有没有什么方法可以从 class 实例中快速填充所有输入控件?
- 除了手动订阅事件处理程序上的每个控件之外,是否有任何方法可以确定哪些输入控件更改了它们的值?
- 有没有什么办法可以改善这一切,例如做事更有效率?
如果您已经传入 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
的键列以及字段 DATE
和 O_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),而不是每个编辑框都添加一个。
我有一个与数据库中的数据绑定的 DataGridView。我需要创建一个表单,其中包含来自单个网格行的数据的输入字段。 表单有 30 多个输入控件 - TextBoxes、Checkboxes 和 NumericUpDowns。
现在我采用了这种方法:
从 DataGridView 中检索当前行并将单元格中的值加载到 class 实例
将实例传递给表单并手动填充输入控件
从表单更新数据库,更新DataGridView
我想改进一些东西:
- 有没有什么方法可以从 class 实例中快速填充所有输入控件?
- 除了手动订阅事件处理程序上的每个控件之外,是否有任何方法可以确定哪些输入控件更改了它们的值?
- 有没有什么办法可以改善这一切,例如做事更有效率?
如果您已经传入 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
的键列以及字段 DATE
和 O_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),而不是每个编辑框都添加一个。