微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在绑定源完成之前触发 Datagridview rows added 事件

如何解决在绑定源完成之前触发 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 举报,一经查实,本站将立刻删除。