Woher bekomme ich die geklickte Row?
Lutz
Lutz Elßner <www.vb-hosting.de> schrieb ...
das sinnvollste (auch damit Validation, Datenbindung usw.0 sauber
funktioniert) dürfte sein, beim CellMouseDown die Zeile zu selektieren:
///
Private Sub DataGridView1_CellMouseDown( _
ByVal sender As System.Object, _
ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs) _
Handles DataGridView1.CellMouseDown
If (e.Button And MouseButtons.Right) = MouseButtons.Right _
AndAlso e.RowIndex <> -1 _
AndAlso e.ColumnIndex <> -1 Then
Me.DataGridView1.CurrentCell = _
Me.DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex)
End If
End Sub
\\\
dann passt CurrentCell usw.
Alternativ sollte für das ContextMenuStrip selbst funktionieren:
///
Private Sub gridContextMenuStrip_Opening( _
ByVal sender As System.Object, _
ByVal e As System.ComponentModel.CancelEventArgs) _
Handles gridContextMenuStrip.Opening
Dim mousePosition As Point = Control.MousePosition
mousePosition = Me.DataGridView1.PointToClient(mousePosition)
Dim hi As DataGridView.HitTestInfo = _
Me.DataGridView1.HitTest(mousePosition.X, mousePosition.Y)
If hi.Type = DataGridViewHitTestType.Cell _
AndAlso hi.RowIndex <> -1 _
AndAlso hi.ColumnIndex <> -1 Then
Try
DataGridView1.CurrentCell = _
Me.DataGridView1.Rows(hi.RowIndex).Cells(hi.ColumnIndex)
Catch ex As Exception
e.Cancel = True
End Try
Else
e.Cancel = True
End If
End Sub
\\\
Gruss
Elmar
ich bin überrascht dass du dich mit "so was" auch beschäftigst..
Ich nehme an dass Microsoft das DataGridView entwickelt hat um es in der
eigenen Software zu benutzen. Und wundere mich dass ich die einfachsten
Dinge nicht hinbekomme. Löschen einer Row mit der DEL Taste funktioniert ja
von alleine, nun will ich mit der rechten Maustaste über dieses Menü
löschen. Das ist alles.
Dein zweites Beispiel funktioniert fast. Allerdings wird die Maus zwei mal
betätigt. Erst in der richtigen Cell die rechte Maustaste. Dann muss man die
Maus im Menü bewegen und über dem richtigen Menüpunkt die linke Maustaste
klicken. Und davon kommen die Koordinaten. Die sind dann unter Umständen
nicht mehr in der Cell. Vielleicht in einer falschen Cell oder auch
außerhalb vom Formular.
Das kann doch nicht so kompliziert sein? Kann das ContextMenuStrip nicht
einfach das Object zurück geben an welches ich es drangehängt habe, und das
ist die Row. Allerdings das RowTemplate und nun gibt es viele Rows..
Immerhin konnte ich etwas über die Verwendung von Koordinaten lernen, das
ist auch was wert.
Lutz
Lutz Elßner <www.vb-hosting.de> schrieb ...
> ich bin überrascht dass du dich mit "so was" auch beschäftigst..
Derzeit beschäftigt mich .NET (allerdings meist in C#) mehr
als der SQL Server.
Für das DataGridView habe allerdings derzeit noch nicht
viel Zeit gefunden.
> Ich nehme an dass Microsoft das DataGridView entwickelt hat um es in
> der eigenen Software zu benutzen.
Naja, eher um zumindest etwas zu bieten, was den kommerziellen
Produkten nahe kommt.
Und wundere mich dass ich die
> einfachsten Dinge nicht hinbekomme. Löschen einer Row mit der DEL
> Taste funktioniert ja von alleine, nun will ich mit der rechten
> Maustaste über dieses Menü löschen. Das ist alles.
Soweit ich das beurteilen kann wäre es am saubersten - gleiche
Ereignisbehandlung usw. - durch eine abgeleitetes DataGridView
hinzukriegen.
Aus dem simplen Grund, weil man nur so auf die protected
Methode "ProcessDeleteKey" Zugriff hat.
Das gilt auch für andere Tastatur-Befehle.
> Dein zweites Beispiel funktioniert fast. Allerdings wird die Maus
> zwei mal betätigt. Erst in der richtigen Cell die rechte Maustaste.
> Dann muss man die Maus im Menü bewegen und über dem richtigen
> Menüpunkt die linke Maustaste klicken. Und davon kommen die
> Koordinaten. Die sind dann unter Umständen nicht mehr in der Cell.
> Vielleicht in einer falschen Cell oder auch außerhalb vom Formular.
Das kann ich so nicht nachvollziehen.
Wobei ich hier zum Testen ein DataGridView mit Standardeinstellungen
verwendet habe.
Könntest Du das mal genauer beschreiben?
Methode 1 - via CellChanged Event - hat allerdings den seltsamen
Effekt, das bei nur teilweise sichtbaren Zeilen der übergebene RowIndex
nicht stimmt (und auch ein Click über den Überschriften) das Ereignis auslöst.
Da es wäre wohl besser auf das MouseDown Event mit HitTestInfo
wie in Methode 2 zu verwenden.
> Allerdings das RowTemplate und nun gibt es viele Rows..
Vom Einsatz via RowTemplate wird im übrigen abgeraten:
http://msdn2.microsoft.com/de-de/library/ha5xt0d9.aspx
Empfohlene Vorgehensweisen für das Skalieren des DataGridView-
Steuerelements in Windows Forms
Gruss
Elmar
> Für das DataGridView habe allerdings derzeit noch nicht
> viel Zeit gefunden.
Und je mehr man Zeit verwendet, desto weniger Code bleibt übrig...
> > Ich nehme an dass Microsoft das DataGridView entwickelt hat um es in
> > der eigenen Software zu benutzen.
>
> Naja, eher um zumindest etwas zu bieten, was den kommerziellen
> Produkten nahe kommt.
Im SQL Server Management Studio ist es mit Sicherheit verwendet worden.
> Soweit ich das beurteilen kann wäre es am saubersten - gleiche
> Ereignisbehandlung usw. - durch eine abgeleitetes DataGridView
> hinzukriegen.
> Aus dem simplen Grund, weil man nur so auf die protected
> Methode "ProcessDeleteKey" Zugriff hat.
> Das gilt auch für andere Tastatur-Befehle.
Der DeleteKey funktioniert ja ohne was zu programmieren. Und diesen aus dem
Kontextmenü aufrufen würde die CurrentRow löschen, die nicht mit der
indentisch sein muss wo die rechte Maustaste geklickt wird.
>
> > Dein zweites Beispiel funktioniert fast. Allerdings wird die Maus
> > zwei mal betätigt. Erst in der richtigen Cell die rechte Maustaste.
> > Dann muss man die Maus im Menü bewegen und über dem richtigen
> > Menüpunkt die linke Maustaste klicken. Und davon kommen die
> > Koordinaten. Die sind dann unter Umständen nicht mehr in der Cell.
> > Vielleicht in einer falschen Cell oder auch außerhalb vom Formular.
>
> Das kann ich so nicht nachvollziehen.
> Wobei ich hier zum Testen ein DataGridView mit Standardeinstellungen
> verwendet habe.
>
> Könntest Du das mal genauer beschreiben?
Man klickt zwei mal erst rechts dann links. Man braucht die Koordinaten vom
Rechtsklick, der Code hat aber die vom Linksklick. Die können -1 sein oder
von einer falschen Cell stammen je nachdem wo die Maus beim zweiten klicken
gerade steht.
> Vom Einsatz via RowTemplate wird im übrigen abgeraten:
> http://msdn2.microsoft.com/de-de/library/ha5xt0d9.aspx
> Empfohlene Vorgehensweisen für das Skalieren des DataGridView-
> Steuerelements in Windows Forms
Ich hatte das ans RowTemplate gehängt weil das Kontextmenü sonst innerhalb
des DGV auch aufgeht wo gar keine Row ist.
Der Link hat mich auf den Weg gebracht. Der Event RowContextMenuStripNeeded
ist der Schlüssel:
Shared Sub DataGridView_RowContextMenuStripNeeded(ByVal sender As Object,
ByVal e As
System.Windows.Forms.DataGridViewRowContextMenuStripNeededEventArgs) _
Handles DataGridView1.RowContextMenuStripNeeded
Dim r As DataGridViewRow = DirectCast(sender,
DataGridView).Rows.Item(e.RowIndex)
If Not r.IsNewRow Then
e.ContextMenuStrip = New ContextMenuStrip
With e.ContextMenuStrip.Items.Add("löschen row " & r.Index, Nothing,
AddressOf ToolStripItem_DataGridViewRow_Remove)
.Tag = r
End With
End If
End Sub
Shared Sub ToolStripItem_DataGridViewRow_Remove(ByVal sender As Object,
ByVal e As System.EventArgs)
Dim r As DataGridViewRow = DirectCast(DirectCast(sender,
ToolStripItem).Tag, DataGridViewRow)
r.DataGridView.Rows.Remove(r)
End Sub
Lutz Elßner <www.vb-hosting.de> schrieb ...
>>> Ich nehme an dass Microsoft das DataGridView entwickelt hat
>>> um es in der eigenen Software zu benutzen.
>>
>> Naja, eher um zumindest etwas zu bieten, was den kommerziellen
>> Produkten nahe kommt.
>
> Im SQL Server Management Studio ist es mit Sicherheit verwendet
> worden.
Die verwenden dort ein eigenes Grid - wie ich irgendwann
mal in Beta Zeiten reflektierte ;-)
>
>> Soweit ich das beurteilen kann wäre es am saubersten - gleiche
>> Ereignisbehandlung usw. - durch eine abgeleitetes DataGridView
>> hinzukriegen.
>> Aus dem simplen Grund, weil man nur so auf die protected
>> Methode "ProcessDeleteKey" Zugriff hat.
>> Das gilt auch für andere Tastatur-Befehle.
>
> Der DeleteKey funktioniert ja ohne was zu programmieren. Und diesen
> aus dem Kontextmenü aufrufen würde die CurrentRow löschen, die nicht
> mit der indentisch sein muss wo die rechte Maustaste geklickt wird.
Deswegen vorher einstellen, CurrentCell beeinflusst auch CurrentRow.
Aber nur mit den Process Methoden kriegst Du ein identisches
Verhalten, so wird dort ebenfalls geprüft ob dem Benutzer das
Löschen erlaubt ist und die Datenquelle es ermöglicht usw. -
was Du sonst selbst prüfen müsstest.
>>> Dein zweites Beispiel funktioniert fast. Allerdings wird die Maus
>>> zwei mal betätigt.
>>
>> Das kann ich so nicht nachvollziehen.
>> Wobei ich hier zum Testen ein DataGridView mit Standardeinstellungen
>> verwendet habe.
>>
>> Könntest Du das mal genauer beschreiben?
>
> Man klickt zwei mal erst rechts dann links. Man braucht die
> Koordinaten vom Rechtsklick, der Code hat aber die vom Linksklick.
Bei mir nicht, egal wie ich das jetzt versucht habe.
> Die können -1 sein oder von einer falschen Cell stammen je
> nachdem wo die Maus beim zweiten klicken gerade steht.
Im Zweifelsfall immer einen HitTest ausführen.
>> Vom Einsatz via RowTemplate wird im übrigen abgeraten:
>> http://msdn2.microsoft.com/de-de/library/ha5xt0d9.aspx
>> Empfohlene Vorgehensweisen für das Skalieren des DataGridView-
>> Steuerelements in Windows Forms
>
> Ich hatte das ans RowTemplate gehängt weil das Kontextmenü sonst
> innerhalb des DGV auch aufgeht wo gar keine Row ist.
auch da wäre ein HitTest vorher das einfachste.
> Der Link hat mich auf den Weg gebracht. Der Event
> RowContextMenuStripNeeded ist der Schlüssel:
>
> Shared Sub DataGridView_RowContextMenuStripNeeded(ByVal sender As
> Object, ByVal e As
> System.Windows.Forms.DataGridViewRowContextMenuStripNeededEventArgs) _
> Handles DataGridView1.RowContextMenuStripNeeded
> Dim r As DataGridViewRow = DirectCast(sender,
> DataGridView).Rows.Item(e.RowIndex)
> If Not r.IsNewRow Then
> e.ContextMenuStrip = New ContextMenuStrip
> With e.ContextMenuStrip.Items.Add("löschen row " & r.Index,
> Nothing, AddressOf ToolStripItem_DataGridViewRow_Remove)
> .Tag = r
ich würds wie in Office machen und das Item anzeigen aber
deaktivieren, so bleiben die Positionen im Kontextmenü
gleich und der Anwender muss nicht immer erst suchen
(wenns später mehrere werden)
> End With
> End If
> End Sub
>
> Shared Sub ToolStripItem_DataGridViewRow_Remove(ByVal sender As
> Object, ByVal e As System.EventArgs)
> Dim r As DataGridViewRow = DirectCast(DirectCast(sender,
> ToolStripItem).Tag, DataGridViewRow)
> r.DataGridView.Rows.Remove(r)
Dann fallen einige Events aus.
Und sollte die Datenquelle mal kein Löschen erlauben gibts
einen Fehler
> End Sub
Gruss
Elmar