2009-08-18 17 views
2

aufgerufen wird Dies ist ein WinForm C# -Anwendungsproblem.DataGridView ruft die Paint-Methode nicht auf, wenn InvalidateCell

Ich habe eine DataGridView und ich brauche einen benutzerdefinierten Typ von DataGridViewColumn so, dass, wenn meine Maus über eine Zelle in dieser Spalte ist, die Zelle etwas Besonderes darauf zeichnet. Ich fand a way des Überschreibens der DataGridViewTextBoxCell, um das Gemälde selbst zu machen. Dieser Artikel zeigt ein Beispiel für die Implementierung einer Rollover-Zelle. Wenn Sie Ihre Maus über eine Zelle bewegen, zeichnet sie ein rotes Rechteck um die Kanten der Zelle.

Wenn Sie das Beispiel sehen, werden Sie feststellen, dass die Art und Weise, wie das Beispiel Daten füllt, direkt Zeilen im Raster erzeugt. Wenn ich die Datenbindung anstelle der direkten Zeilenfüllung verwende, stelle ich fest, dass die Zellen sich am Anfang nicht selbst zeichnen. Eigentlich müssen Sie zuerst eine Zelle auswählen, dann werden alle Zellen in dieser Zeile korrekt dargestellt. Wenn Sie keine Zelle einer Zeile auswählen, werden alle Zellen in dieser Zeile nicht entsprechend angezeigt, wenn sich die Maus über ihnen befindet.

Ich denke, dies ist eine Art Optimierung des Gitters, so dass, wenn Sie eine Zelle auswählen, das zugrunde liegende Objekt dieser Zeile aktiviert ist und das Gitter Paint-Methode aufrufen, wenn InvlidateCell-Methode Aufruf ist. Wenn das zugrunde liegende Objekt einer Zeile jedoch nicht aktiviert ist, wird das Raster die Zellen standardmäßig malen, um Zeit zu sparen.

Offensichtlich brauche ich nicht die Optimierung, sondern den langsamen Weg. In meinem Fall spielt es keine Rolle, da meine Daten in diesem Raster niemals zu groß werden. Wie kann ich es erreichen? Ich versuche, grid.Refresh() aufzurufen, nachdem die Daten an das Raster gebunden sind, aber das hilft nicht.

Vielen Dank für Ihren Vorschlag.

Ji

+0

Wenn ich this.DataGridView.Refresh() in der OnMouseEnter und OnMouseLeave Methoden setzen, ist das Problem behoben. Dies führt jedoch dazu, dass das gesamte Gitter blinkt, während sich die Maus darauf bewegt. Ich glaube, es ist keine gute Lösung. – Steve

Antwort

0

Nicht ganz sicher, dass ich Ihre Frage verstanden habe. Nur sehen, ob dies etwas wie das, was Sie brauchen:

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

Was ich meine ist, wenn Sie InvalidateCell-Methode im überschriebenen OnMouseEnter-Ereignis der angepassten Zelle aufrufen, jedes Mal, wenn die InvalidateCell-Methode aufgerufen wird, sollte auch die Paint-Methode des Zellobjekts aufgerufen werden. Dies trifft jedoch nicht zu, wenn Sie die Datenbindung im Grid verwenden. Bei der Datenbindung löst die anfängliche InvalidateCell-Methode die Paint-Methode nicht aus. Dies geschieht nur, wenn Sie eine Zelle auswählen. Sobald eine Zelle ausgewählt ist, verhalten sich alle Zellen in ihrer Zeile normal: Die InvalidateCell-Methode löst immer die Paint-Methode aus. Ich habe schon Ihren Vorschlag ausprobiert. Es blinkt die Zelle, während sich die Maus bewegt, was schlecht ist – Steve

0

ich mit dem gleichen Problem für eine Weile zu kämpfen haben, das Problem ist, dass jede Methode in DataGridViewImageButtonCell : DataGridViewTextBoxCell mit Objektattribut bezeichnet wird RowIndex = -1 daher InvalidateCell() bekommt ausgelöst mit rowIndex = -1 so passiert nichts.

Dies wird durch rows being shared verursacht:

Wenn die RowIndex Eigenschaft -1 zurückgibt, ist die Zelle entweder ein Spaltenkopf oder der Zeile der Zelle geteilt wird.

MSDN shows some ways, wie Sie Zeilen shared halten können (also gegen sie gehen = unshare Reihe), einschließlich:

Zum Beispiel kann eine Zeile nicht in einem der folgenden Situationen gemeinsam genutzt werden können:

  • Die Zeile enthält eine einzelne ausgewählte Zelle, die sich nicht in einer ausgewählten Spalte befindet.
  • Die Zeile enthält eine Zelle mit den Eigenschaften ToolTipText oder ContextMenuStrip.
  • Die Zeile enthält eine DataGridViewComboBoxCell mit der Eigenschaft Items.

...

Sie das DataGridViewRowCollection.CollectionChanged oder DataGridView.RowStateChanged Ereignisse nicht behandeln. Diese Ereignisse bewirken, dass Zeilen nicht freigegeben werden. Rufen Sie auch nicht die Methoden DataGridViewRowCollection.OnCollectionChanged oder DataGridView.OnRowStateChanged auf, die diese Ereignisse auslösen.

Ich habe versucht mit:

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

void MyDataGridView_RowStateChanged(object sender, 
     DataGridViewRowStateChangedEventArgs e) 
{ 
} 

Es funktionierte, aber ich hasste die Idee der Sperren von Zeilen standardmäßig, also habe ich Verlängerung durch Überlastung meine Cell Klasse am Ende:

So endgültigen Arbeits Code wie folgt aussieht:

/// <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; 
} 
Verwandte Themen