2009-08-18 44 views
2

这是一个WinForm C#应用程序问题。当调用InvalidateCell时,DataGridView不调用Paint方法

我有一个DataGridView,我需要一个定制类型的DataGridViewColumn的,这样当我的鼠标在该列的单元格,单元格绘制一些特别的东西就可以了。我发现a way覆盖DataGridViewTextBoxCell自己做绘画。那篇文章展示了一个实现翻转单元的例子,当你将鼠标移动到一个单元格上时,它会在它自身的边界上绘制一个红色的矩形。

如果您看到该示例,您会发现示例填充数据的方式是直接将行创建到网格。当我使用数据绑定而不是直接行填充时,我发现单元格不会在开始时自己绘制。实际上,您必须先选择一个单元格,然后该行上的所有单元格才能正确绘制。如果您没有选择某一行的单元格,则该行上的所有单元格都不会在鼠标悬停在其上时进行相应的绘制。

我认为这是网格的某种优化,当你选择一个单元格时,该行的底层对象被激活,当InvlidateCell方法被调用时,网格将调用Paint方法。但是如果一行的底层对象没有被激活,那么网格将只使用默认方法绘制单元格以节省时间。

显然,我不需要优化,但速度慢。这对我来说并不重要,因为我在这个网格上的数据永远不会太大。我怎样才能实现它?我试图在数据绑定到网格后调用grid.Refresh(),但这没有帮助。

谢谢您的建议。

Ji

+0

如果我把this.DataGridView.Refresh()在OnMouseEnter在和OnMouseLeave在方法,问题是固定的。但是这会导致整个网格在鼠标移动时闪烁。我相信这不是一个好的解决方案。 – Steve 2009-08-18 07:05:20

回答

0

不完全确定我明白你的问题。只要看看这是否有点像你需要:

bool bSomeFlag = false; 
int iCol = 0; 
int iRow = 0; 
private void dataGridView1_CellMouseMove(object sender, DataGridViewCellMouseEventArgs e) { 
      iCol = e.ColumnIndex; 
      iRow = e.RowIndex; 
      bSomeFlag = true; 
      this.dataGridView1.Invalidate(); 
     } 
private void dataGridView1_Paint(object sender, PaintEventArgs e) { 
      if (bSomeFlag && iRow >=0 && iCol>=0) { 
       dataGridView1.Rows[iRow].Cells[iCol].Style.BackColor = Color.Red; 
      } 
     } 
+0

我的意思是,如果您在自定义单元格的重写OnMouseEnter事件中调用InvalidateCell方法,则每次调用InvalidateCell方法时,也应该调用单元格对象的Paint方法。但是,如果您在网格上使用数据绑定,则情况并非如此。对于数据绑定,最初InvalidateCell方法不会触发Paint方法。这只会在您选择一个单元时发生。选中单元格后,其行中的所有单元格都会正常运行:InvalidateCell方法始终会触发Paint方法。 我已经尝试了您的建议。当鼠标移动时,它会使单元闪烁,这是不好的 – Steve 2009-08-18 08:25:40

0

我已经有一段同样的问题挣扎,问题是,在DataGridViewImageButtonCell : DataGridViewTextBoxCell任何方法被调用对象属性RowIndex = -1,因此InvalidateCell()得到由rowIndex = -1触发,所以没有任何反应。

这是通过引起rows being shared

当RowIndex属性返回-1,所述细胞可以是一个列标题,或细胞的行共享

MSDN shows some ways可以如何保持行共享(因此逆着它们=取消共享行),包括:

例如,行不能在任何以下 情况共享

  • 该行包含不在选定列中的单个选定单元格。
  • 该行包含一个其ToolTipText或ContextMenuStrip属性设置的单元。
  • 该行包含DataGridViewComboBoxCell及其Items属性集。

...

,请勿触摸DataGridViewRowCollection.CollectionChanged或DataGridView.RowStateChanged事件。这些事件导致行被取消共享。另外,不要调用引发这些事件的DataGridViewRowCollection.OnCollectionChanged或DataGridView.OnRowStateChanged方法。

我已经尝试使用:

public MyDataGridView() 
    : base() 
{ 
    RowStateChanged += MyDataGridView_RowStateChanged; 
} 

void MyDataGridView_RowStateChanged(object sender, 
     DataGridViewRowStateChangedEventArgs e) 
{ 
} 

它的工作,但我讨厌在默认情况下不共享行的想法,所以我最终被超载延长我的Cell类:

所以最终工作的代码如下所示:

/// <summary> 
/// Required correcting mousve hover displaying 
/// </summary> 
/// <param name="rowIndex"></param> 
/// <returns></returns> 
protected override bool MouseEnterUnsharesRow(int rowIndex) 
{ 
    return true; 
} 

/// <summary> 
/// Required correcting mousve hover displaying 
/// </summary> 
/// <param name="rowIndex"></param> 
/// <returns></returns> 
protected override bool MouseLeaveUnsharesRow(int rowIndex) 
{ 
    return true; 
}