如何解决在绑定源完成之前触发 Datagridview rows added 事件
首先我有什么:
我得到了一个 datagridview 和 bindsource(目前我自己的数据表来自 sql 调用)。 bindsource 有多个列,但其中一个是我的数据的特定“位置”列。
我想做什么:
当我将 bindsource 设置为 datagridview 时,我想更改具有指定“位置”的行的颜色。
我做了什么:
我认为创建一个 RowsAdded 事件并检查添加行的“位置”列是否等于我指定的位置就足够了。基于此,我会更改行的背景色。
代码如下:
private void setBindSource(BindingSource bindSource)
{
gridview.DataSource = bindSource;
gridview.EndEdit();
bindSource.EndEdit();
}
private void gridView_RowsAdded(object sender,System.Windows.Forms.DataGridViewRowsAddedEventArgs e)
{
if (e.RowIndex == -1 || e.RowCount == 0)
{
return;
}
for (int index = e.RowIndex; index <= e.RowIndex + e.RowCount - 1; index++)
{
DataGridView dgv = sender as DataGridView;
DataGridViewRow row = dgv.Rows[index];
if ((Int32)row.Cells["position"].Value == specificPosition)
row.DefaultCellStyle.BackColor = Color.Green;
}
}
我面临的问题:
rows added 事件按预期触发(在 gridview.DataSource = bindSource; 处)。但是该行本身没有任何数据(使用的数据表显示了预期的数据)。所以它显然会抛出错误,即找不到指定的列“位置”。我假设 gridview 还没有完全初始化?
如何在添加行时更改行的颜色?
解决方法
当一行的背景颜色取决于特定的单元格值时,在“更改”行颜色时应注意一些事项。
用于测试特定单元格值和更改行颜色的代码所在的“位置”可以在许多不同的网格事件中完成,并且所有事件(基本上)都将完成相同的事情。但是,做一些简单的测试来帮助您确定您选择的“网格事件”是否“真正”是您需要或应该使用的可能会有所帮助。
例如,如建议的那样,您可以订阅 grids CellFormatting
事件来执行您所描述的操作,并且它会按预期工作。但是,使用此事件会产生一个微妙但可能有问题的问题。首先,几乎所有的网格“格式化”事件都会触发很多次。
如果用户只是将光标移动到网格上,则格式化事件将触发。因此,如果光标恰好移动到目标单元格上,则执行代码。这可能是可以接受的;然而,从这里很明显,检查单元格值实际上是不必要的,因为单元格值没有改变。用户只需将光标移到目标单元格上即可。
如前所述,这可能是可以接受的,但是,如果将相同的不必要的事件调用混合在一起,则不难看出这种情况的许多组合可能会影响 UI 的性能,并且用户可能会体验到缓慢的 UI .
这里的主要思想......是不要将您的代码放在一个事件中,因为该事件将被不必要地触发,这是一个很好的例子。它可能有效,但代码正在“创建”额外和不必要的执行步骤。
鉴于此,您尝试连接网格 RowsAdded
事件可能会奏效。但是,正如您所指出的,当数据“初始”加载时以及用户手动添加新行或代码添加新行时,似乎需要做一些不同的事情。当数据“初始”加载时,您是正确的,某些单元格可能尚未初始化。至少是您的代码正在查看的单元格。
这可以解决,但是,使用 RowsAdded
事件会遗漏另一个场景......
_“如果用户更改‘位置’单元格的单元格值怎么办?”
在这种情况下不会触发新行事件。如果用户将“位置”单元格更改为 specifiedPosition
的值,则该行的背景颜色不会更改。
考虑到所有这些,为了提供帮助,最好指出我们希望代码运行的“何时”。从我所看到的,这将是“当”位置列中的单元格中的值发生变化时。因此,我建议您订阅 grids CellValueChanged
事件。如果“更改”的单元格是“位置”单元格,则测试单元格值并相应地为行着色。
这将最大限度地减少不必要的代码调用次数,并在用户“更改”单元格值时解决之前描述的问题。当“用户”添加新行时,这也将起作用。不幸的是,当最初加载数据或通过代码添加新行时,不会触发此事件。
鉴于此,除了在代码中为新添加的行设置适当的行颜色之外,还有一种可能的解决方案是在网格初始加载数据后为行着色,一些小方法可能会派上用场。
第一种方法会根据“位置”单元格的值简单地为一 (1) 行着色。这假设给定的行不是 null
并且位置列存在并且它是有效的 int.
private void ColorRow(DataGridViewRow row) {
if ((int)row.Cells["position"].Value == specificPosition) {
row.DefaultCellStyle.BackColor = Color.LightGreen;
}
else {
row.DefaultCellStyle.BackColor = Color.White;
}
}
我们可以在 grids ColorRow
事件中使用 CellValueChanged
方法为特定行着色。此外,在表单加载事件中,在数据初始设置到网格中后,我们可以调用一个额外的方法,该方法简单地循环遍历网格的所有行并调用上面的 ColorRow
方法。这个 ColorSpecificRows
方法可能看起来像……
private void ColorSpecificRows() {
foreach (DataGridViewRow row in gridView.Rows) {
if (!row.IsNewRow) {
ColorRow(row);
}
}
}
接下来,剩下的就是订阅 grids CellValueChanged
事件,它可能看起来像……
private void gridView_CellValueChanged(object sender,DataGridViewCellEventArgs e) {
ColorRow(gridView.Rows[e.RowIndex]);
}
为了帮助测试这一点,下面是一个完整的示例。创建一个新的 win 表单解决方案,向表单添加一个 DataGridView
和一个 Button
。该按钮用于演示以编程方式添加行。
DataTable GridTable;
BindingSource GridBS;
Random rand = new Random();
int specificPosition = 2;
int formattingCount = 0;
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender,EventArgs e) {
GridTable = GetTable();
FillTable(GridTable);
GridBS = new BindingSource(GridTable,null);
gridView.DataSource = GridBS;
ColorSpecificRows();
}
private DataTable GetTable() {
DataTable dt = new DataTable();
dt.Columns.Add("Col0",typeof(string));
dt.Columns.Add("position",typeof(int));
dt.Columns.Add("Col2",typeof(string));
return dt;
}
private void FillTable(DataTable dt) {
for (int i = 0; i < 10; i++) {
dt.Rows.Add("C0R" + i,rand.Next(1,4),"C2R" + i);
}
}
private void button1_Click(object sender,EventArgs e) {
GridTable.Rows.Add("new0",2,"new0");
GridTable.Rows.Add("new1",3,"new0");
GridTable.Rows.Add("new2","new0");
ColorSpecificRows();
}
最后,出于测试目的,您可以连接 grids CellFormatting
事件以演示该事件的调用频率。
private void gridView_CellFormatting(object sender,DataGridViewCellFormattingEventArgs e) {
Debug.WriteLine("CellFormatting - Enter -- FormattingCount: " + ++formattingCount);
// code to change row color
Debug.WriteLine("CellFormatting - Leave");
}
我希望这是有道理的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。