Fix: InvalidRowHandle bei Doppelklick auf GroupRow in Item_Scope
Item_Scope() hat den RowHandle über CalcHitInfo(GridCursorLocation) neu berechnet - basierend auf einer zwischengespeicherten Klick- Position. Klappt sich eine Gruppe zwischen Klick und Verarbeitung auf/zu (automatisch durch den DoubleClick-Handler oder manuell durch den User), verschiebt sich die RowHandle-Nummerierung und die gecachte Position zeigt ins Leere -> InvalidRowHandle -> Doppelklick auf Gruppenkopf verpuffte wirkungslos. - Fallback auf GridViewWorkflows.FocusedRowHandle, wenn der aus GridCursorLocation berechnete RowHandle ungültig ist. - Group-/DataRow-Erkennung erfolgt jetzt einheitlich per IsGroupRow/IsDataRow(effectiveRowHandle) statt über die potenziell unzuverlässigen hitInfo.InGroupRow/InDataRow-Flags; dieser Pfad war zuvor bereits als Bug-Workaround vorhanden und wird nun durchgängig genutzt (Schritt-1/Schritt-2-Duplizierung entfernt). - Doppelten "STARTEDROM NORMALISIEREN"-Codeblock (Copy-Paste-Rest) bereinigt. Betrifft sowohl den Doppelklick-Pfad als auch die manuellen Aufrufe über die Kontextmenü-Buttons (CMROW/CMGROUP), da beide denselben Codepfad in Item_Scope durchlaufen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2532,70 +2532,60 @@ Public Class frmMain
|
|||||||
' ========== HITINFO NUR EINMAL BERECHNEN ==========
|
' ========== HITINFO NUR EINMAL BERECHNEN ==========
|
||||||
Dim hitInfo As GridHitInfo = GridViewWorkflows.CalcHitInfo(GridCursorLocation)
|
Dim hitInfo As GridHitInfo = GridViewWorkflows.CalcHitInfo(GridCursorLocation)
|
||||||
|
|
||||||
' ===== FRÜHE VALIDIERUNG: UNGÜLTIGE ROWHANDLES ABFANGEN =====
|
' ===== EFFEKTIVEN ROWHANDLE ERMITTELN (MIT FALLBACK) =====
|
||||||
If hitInfo.RowHandle = DevExpress.XtraGrid.GridControl.InvalidRowHandle Then
|
' hitInfo basiert auf der zwischengespeicherten Klick-Position (GridCursorLocation).
|
||||||
LOGGER.Warn($"⚠️ Item_Scope: InvalidRowHandle detected (click on empty grid area?) - exiting")
|
' Diese kann zwischen Klick und Verarbeitung ungültig werden - z.B. wenn eine Gruppe
|
||||||
Exit Function
|
' zwischenzeitlich auf-/zugeklappt wurde (automatisch durch den DoubleClick-Handler
|
||||||
|
' oder manuell durch den User) und sich dadurch die RowHandle-Nummerierung verschoben hat.
|
||||||
|
' In diesem Fall auf FocusedRowHandle ausweichen, das vom Grid selbst nachgeführt wird
|
||||||
|
' und i.d.R. weiterhin die angeklickte Zeile referenziert.
|
||||||
|
Dim effectiveRowHandle As Integer = hitInfo.RowHandle
|
||||||
|
|
||||||
|
If effectiveRowHandle = DevExpress.XtraGrid.GridControl.InvalidRowHandle Then
|
||||||
|
Dim focusedRowHandle = GridViewWorkflows.FocusedRowHandle
|
||||||
|
If focusedRowHandle <> DevExpress.XtraGrid.GridControl.InvalidRowHandle Then
|
||||||
|
LOGGER.Debug($"Item_Scope: CalcHitInfo(GridCursorLocation) invalid - falling back to FocusedRowHandle [{focusedRowHandle}]")
|
||||||
|
effectiveRowHandle = focusedRowHandle
|
||||||
|
Else
|
||||||
|
LOGGER.Warn($"⚠️ Item_Scope: InvalidRowHandle detected (click on empty grid area?) - exiting")
|
||||||
|
Exit Function
|
||||||
|
End If
|
||||||
End If
|
End If
|
||||||
|
|
||||||
' ===== ZUSÄTZLICH: Prüfen ob überhaupt eine Zeile getroffen wurde =====
|
' ===== GROUP-/DATAROW DIREKT AM ROWHANDLE PRÜFEN =====
|
||||||
If Not hitInfo.InRow Then
|
' Robuster als hitInfo.InGroupRow/InDataRow: funktioniert unverändert für den
|
||||||
LOGGER.Warn($"⚠️ Item_Scope: Click not in any row (HitTest:[{hitInfo.HitTest}]) - exiting")
|
' FocusedRowHandle-Fallback und umgeht einen bekannten DevExpress-Bug, bei dem
|
||||||
|
' diese hitInfo-Flags trotz gültigem RowHandle falsch gesetzt sein können.
|
||||||
|
Dim isGroupRow As Boolean = GridViewWorkflows.IsGroupRow(effectiveRowHandle)
|
||||||
|
Dim isDataRow As Boolean = GridViewWorkflows.IsDataRow(effectiveRowHandle)
|
||||||
|
|
||||||
|
If Not isGroupRow AndAlso Not isDataRow Then
|
||||||
|
LOGGER.Warn($"⚠️ Item_Scope: RowHandle [{effectiveRowHandle}] ist weder Group- noch DataRow - exiting")
|
||||||
Exit Function
|
Exit Function
|
||||||
End If
|
End If
|
||||||
|
|
||||||
' ===== STARTEDROM NORMALISIEREN =====
|
' ===== STARTEDROM NORMALISIEREN =====
|
||||||
If startedFrom = "DOUBLECLICK" Then
|
If startedFrom = "DOUBLECLICK" Then
|
||||||
startedFrom = If(hitInfo.InGroupRow, "CMGROUP", "CMROW")
|
startedFrom = If(isGroupRow, "CMGROUP", "CMROW")
|
||||||
LOGGER.Debug($"User clicked {If(hitInfo.InGroupRow, "group", "normal")} row.")
|
LOGGER.Debug($"User clicked {If(isGroupRow, "group", "normal")} row.")
|
||||||
End If
|
|
||||||
' ========== STARTEDROM NORMALISIEREN ==========
|
|
||||||
If startedFrom = "DOUBLECLICK" Then
|
|
||||||
startedFrom = If(hitInfo.InGroupRow, "CMGROUP", "CMROW")
|
|
||||||
LOGGER.Debug($"User clicked {If(hitInfo.InGroupRow, "group", "normal")} row.")
|
|
||||||
End If
|
End If
|
||||||
|
|
||||||
' ========== PROFIL-ID ERMITTELN (OPTIMIERT) ==========
|
' ========== PROFIL-ID ERMITTELN ==========
|
||||||
' ========== PROFIL-ID ERMITTELN (MIT FALLBACK-LOGIK) ==========
|
|
||||||
Dim oHitProfilID As Object = Nothing
|
Dim oHitProfilID As Object = Nothing
|
||||||
|
|
||||||
' ===== SCHRITT 1: Direkte Erkennung versuchen =====
|
If isGroupRow Then
|
||||||
If hitInfo.InGroupRow Then
|
|
||||||
' ✅ Gruppenkopf: Profil-ID aus erster Datenzeile der Gruppe
|
' ✅ Gruppenkopf: Profil-ID aus erster Datenzeile der Gruppe
|
||||||
oHitProfilID = GridViewWorkflows.GetRowCellValue(
|
oHitProfilID = GridViewWorkflows.GetRowCellValue(
|
||||||
GridViewWorkflows.GetDataRowHandleByGroupRowHandle(hitInfo.RowHandle),
|
GridViewWorkflows.GetDataRowHandleByGroupRowHandle(effectiveRowHandle),
|
||||||
GridViewWorkflows.Columns("PROFILE_ID"))
|
GridViewWorkflows.Columns("PROFILE_ID"))
|
||||||
LOGGER.Debug("Clicked on Group Row")
|
LOGGER.Debug("Clicked on Group Row")
|
||||||
|
|
||||||
ElseIf hitInfo.InDataRow Then
|
ElseIf isDataRow Then
|
||||||
' ✅ Normale Datenzeile: Profil-ID direkt aus dieser Zeile
|
' ✅ Normale Datenzeile: Profil-ID direkt aus dieser Zeile
|
||||||
oHitProfilID = GridViewWorkflows.GetRowCellValue(
|
oHitProfilID = GridViewWorkflows.GetRowCellValue(
|
||||||
hitInfo.RowHandle,
|
effectiveRowHandle,
|
||||||
GridViewWorkflows.Columns("PROFILE_ID"))
|
GridViewWorkflows.Columns("PROFILE_ID"))
|
||||||
LOGGER.Debug("Clicked on Data Row")
|
LOGGER.Debug("Clicked on Data Row")
|
||||||
|
|
||||||
Else
|
|
||||||
' ===== SCHRITT 2: FALLBACK für "unklare" Klicks =====
|
|
||||||
' Wenn hitInfo weder InGroupRow noch InDataRow ist, RowHandle direkt prüfen
|
|
||||||
LOGGER.Warn($"⚠️ hitInfo ist WEDER InGroupRow noch InDataRow - RowHandle:[{hitInfo.RowHandle}]")
|
|
||||||
|
|
||||||
If GridViewWorkflows.IsGroupRow(hitInfo.RowHandle) Then
|
|
||||||
' Es ist doch eine Gruppe (DevExpress Bug-Workaround)
|
|
||||||
LOGGER.Debug("Fallback: IsGroupRow(RowHandle) = True")
|
|
||||||
oHitProfilID = GridViewWorkflows.GetRowCellValue(
|
|
||||||
GridViewWorkflows.GetDataRowHandleByGroupRowHandle(hitInfo.RowHandle),
|
|
||||||
GridViewWorkflows.Columns("PROFILE_ID"))
|
|
||||||
|
|
||||||
ElseIf GridViewWorkflows.IsDataRow(hitInfo.RowHandle) Then
|
|
||||||
' Es ist doch eine Datenzeile (DevExpress Bug-Workaround)
|
|
||||||
LOGGER.Debug("Fallback: IsDataRow(RowHandle) = True")
|
|
||||||
oHitProfilID = GridViewWorkflows.GetRowCellValue(
|
|
||||||
hitInfo.RowHandle,
|
|
||||||
GridViewWorkflows.Columns("PROFILE_ID"))
|
|
||||||
|
|
||||||
Else
|
|
||||||
LOGGER.Error($"⚠️ RowHandle [{hitInfo.RowHandle}] ist weder Group noch DataRow!")
|
|
||||||
End If
|
|
||||||
End If
|
End If
|
||||||
|
|
||||||
LOGGER.Debug("Clicked ProfileId: [{0}], Started From: [{1}]", oHitProfilID, startedFrom)
|
LOGGER.Debug("Clicked ProfileId: [{0}], Started From: [{1}]", oHitProfilID, startedFrom)
|
||||||
@@ -2619,15 +2609,15 @@ Public Class frmMain
|
|||||||
Dim oGroupRowHandle As Integer
|
Dim oGroupRowHandle As Integer
|
||||||
|
|
||||||
' KRITISCH: Den RICHTIGEN Gruppen-Handle ermitteln
|
' KRITISCH: Den RICHTIGEN Gruppen-Handle ermitteln
|
||||||
If GridViewWorkflows.IsGroupRow(hitInfo.RowHandle) Then
|
If isGroupRow Then
|
||||||
' User hat direkt auf die Gruppen-Zeile geklickt
|
' User hat direkt auf die Gruppen-Zeile geklickt
|
||||||
oGroupRowHandle = hitInfo.RowHandle
|
oGroupRowHandle = effectiveRowHandle
|
||||||
LOGGER.Debug($"User clicked directly on group row, handle: {oGroupRowHandle}")
|
LOGGER.Debug($"User clicked directly on group row, handle: {oGroupRowHandle}")
|
||||||
Else
|
Else
|
||||||
' User hat auf eine Daten-Zeile INNERHALB einer Gruppe geklickt
|
' User hat auf eine Daten-Zeile INNERHALB einer Gruppe geklickt
|
||||||
' → Parent-Gruppe ermitteln
|
' → Parent-Gruppe ermitteln
|
||||||
oGroupRowHandle = GridViewWorkflows.GetParentRowHandle(hitInfo.RowHandle)
|
oGroupRowHandle = GridViewWorkflows.GetParentRowHandle(effectiveRowHandle)
|
||||||
LOGGER.Debug($"User clicked on data row {hitInfo.RowHandle}, parent group handle: {oGroupRowHandle}")
|
LOGGER.Debug($"User clicked on data row {effectiveRowHandle}, parent group handle: {oGroupRowHandle}")
|
||||||
|
|
||||||
If Not GridViewWorkflows.IsGroupRow(oGroupRowHandle) Then
|
If Not GridViewWorkflows.IsGroupRow(oGroupRowHandle) Then
|
||||||
LOGGER.Warn($"⚠️ Parent handle {oGroupRowHandle} is not a group row!")
|
LOGGER.Warn($"⚠️ Parent handle {oGroupRowHandle} is not a group row!")
|
||||||
@@ -2756,12 +2746,12 @@ Public Class frmMain
|
|||||||
' ========== PROFIL-TITEL ERMITTELN ==========
|
' ========== PROFIL-TITEL ERMITTELN ==========
|
||||||
Dim PROFIL_TITLE As String = String.Empty
|
Dim PROFIL_TITLE As String = String.Empty
|
||||||
|
|
||||||
If hitInfo.InGroupRow Then
|
If isGroupRow Then
|
||||||
GridViewItem_Clicked = "GROUP"
|
GridViewItem_Clicked = "GROUP"
|
||||||
startedFrom = "CMGROUP"
|
startedFrom = "CMGROUP"
|
||||||
LOGGER.Debug($"Item_Scope: InGroupRow")
|
LOGGER.Debug($"Item_Scope: InGroupRow")
|
||||||
|
|
||||||
Dim groupRowText = GridViewWorkflows.GetGroupRowDisplayText(hitInfo.RowHandle)
|
Dim groupRowText = GridViewWorkflows.GetGroupRowDisplayText(effectiveRowHandle)
|
||||||
LOGGER.Debug($"Item_Scope: groupRowText {groupRowText}")
|
LOGGER.Debug($"Item_Scope: groupRowText {groupRowText}")
|
||||||
|
|
||||||
If GRID_LOAD_TYPE = "OVERVIEW" Then
|
If GRID_LOAD_TYPE = "OVERVIEW" Then
|
||||||
@@ -2770,14 +2760,14 @@ Public Class frmMain
|
|||||||
PROFIL_TITLE = If(splitIndex >= 0, groupRowText.Substring(0, splitIndex).Trim(), groupRowText)
|
PROFIL_TITLE = If(splitIndex >= 0, groupRowText.Substring(0, splitIndex).Trim(), groupRowText)
|
||||||
End If
|
End If
|
||||||
|
|
||||||
ElseIf hitInfo.InDataRow Then
|
ElseIf isDataRow Then
|
||||||
GridViewItem_Clicked = "ROW"
|
GridViewItem_Clicked = "ROW"
|
||||||
LOGGER.Debug($"Item_Scope: InDataRow")
|
LOGGER.Debug($"Item_Scope: InDataRow")
|
||||||
|
|
||||||
If GRID_LOAD_TYPE = "OVERVIEW" Then
|
If GRID_LOAD_TYPE = "OVERVIEW" Then
|
||||||
LOGGER.Debug($"Item_Scope: GRID_LOAD_TYPE = OVERVIEW")
|
LOGGER.Debug($"Item_Scope: GRID_LOAD_TYPE = OVERVIEW")
|
||||||
Dim groupRowText = GridViewWorkflows.GetGroupRowDisplayText(
|
Dim groupRowText = GridViewWorkflows.GetGroupRowDisplayText(
|
||||||
GridViewWorkflows.GetParentRowHandle(hitInfo.RowHandle))
|
GridViewWorkflows.GetParentRowHandle(effectiveRowHandle))
|
||||||
LOGGER.Debug($"Item_Scope: OVERVIEWgroupRowText {groupRowText}")
|
LOGGER.Debug($"Item_Scope: OVERVIEWgroupRowText {groupRowText}")
|
||||||
|
|
||||||
groupRowText = groupRowText.Replace("Profile (Fixed): ", "").Trim()
|
groupRowText = groupRowText.Replace("Profile (Fixed): ", "").Trim()
|
||||||
@@ -2806,16 +2796,16 @@ Public Class frmMain
|
|||||||
If Not IsNothing(CURRENT_CLICKED_PROFILE_ID) AndAlso IsNumeric(CURRENT_CLICKED_PROFILE_ID) Then
|
If Not IsNothing(CURRENT_CLICKED_PROFILE_ID) AndAlso IsNumeric(CURRENT_CLICKED_PROFILE_ID) Then
|
||||||
LOGGER.Debug($"Item_Scope: Valid PROFIL_ID")
|
LOGGER.Debug($"Item_Scope: Valid PROFIL_ID")
|
||||||
|
|
||||||
If hitInfo.InGroupRow OrElse (startedFrom = "CMGROUP" AndAlso hitInfo.InDataRow) Then
|
If isGroupRow OrElse (startedFrom = "CMGROUP" AndAlso isDataRow) Then
|
||||||
' GRUPPE: Workflow ohne spezifisches Dokument
|
' GRUPPE: Workflow ohne spezifisches Dokument
|
||||||
Reset_Current()
|
Reset_Current()
|
||||||
CURRENT_ProfilGUID = CURRENT_CLICKED_PROFILE_ID
|
CURRENT_ProfilGUID = CURRENT_CLICKED_PROFILE_ID
|
||||||
LOGGER.Debug($"Item_Scope: hitInfo.InGroupRow...CURRENT_CLICKED_PROFILE_ID [{CURRENT_CLICKED_PROFILE_ID}]")
|
LOGGER.Debug($"Item_Scope: isGroupRow...CURRENT_CLICKED_PROFILE_ID [{CURRENT_CLICKED_PROFILE_ID}]")
|
||||||
Load_Profil_from_Grid(CURRENT_CLICKED_PROFILE_ID)
|
Load_Profil_from_Grid(CURRENT_CLICKED_PROFILE_ID)
|
||||||
|
|
||||||
ElseIf hitInfo.InDataRow Then
|
ElseIf isDataRow Then
|
||||||
' EINZELNE ZEILE: Mit spezifischem Dokument
|
' EINZELNE ZEILE: Mit spezifischem Dokument
|
||||||
LOGGER.Debug($"Item_Scope: hitInfo.InDataRow...")
|
LOGGER.Debug($"Item_Scope: isDataRow...")
|
||||||
|
|
||||||
' ========== DOKUMENT-DATEN ABRUFEN ==========
|
' ========== DOKUMENT-DATEN ABRUFEN ==========
|
||||||
Dim oFocusedDocGUID = GridViewWorkflows.GetFocusedRowCellValue(GridViewWorkflows.Columns("GUID"))
|
Dim oFocusedDocGUID = GridViewWorkflows.GetFocusedRowCellValue(GridViewWorkflows.Columns("GUID"))
|
||||||
@@ -2823,7 +2813,7 @@ Public Class frmMain
|
|||||||
|
|
||||||
' Validierungen
|
' Validierungen
|
||||||
If oFocusedDocID Is Nothing Then
|
If oFocusedDocID Is Nothing Then
|
||||||
LOGGER.Warn("⚠️ In hitInfo.InDataRow: DocID is nothing!!!")
|
LOGGER.Warn("⚠️ In isDataRow: DocID is nothing!!!")
|
||||||
bsiMessage.Caption = "Error getting DocID!"
|
bsiMessage.Caption = "Error getting DocID!"
|
||||||
bsiMessage.ItemAppearance.Normal.BackColor = Color.Red
|
bsiMessage.ItemAppearance.Normal.BackColor = Color.Red
|
||||||
bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black
|
bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black
|
||||||
@@ -2831,7 +2821,7 @@ Public Class frmMain
|
|||||||
End If
|
End If
|
||||||
|
|
||||||
If oFocusedDocGUID Is Nothing Then
|
If oFocusedDocGUID Is Nothing Then
|
||||||
LOGGER.Warn("⚠️ In hitInfo.InDataRow: oFocusedDocGUID is nothing!!!")
|
LOGGER.Warn("⚠️ In isDataRow: oFocusedDocGUID is nothing!!!")
|
||||||
bsiMessage.Caption = "Error getting DocGUID!"
|
bsiMessage.Caption = "Error getting DocGUID!"
|
||||||
bsiMessage.ItemAppearance.Normal.BackColor = Color.Red
|
bsiMessage.ItemAppearance.Normal.BackColor = Color.Red
|
||||||
bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black
|
bsiMessage.ItemAppearance.Normal.ForeColor = Color.Black
|
||||||
@@ -3380,8 +3370,17 @@ Public Class frmMain
|
|||||||
|
|
||||||
' ===== FRÜHE VALIDIERUNG =====
|
' ===== FRÜHE VALIDIERUNG =====
|
||||||
If hitInfo.RowHandle = DevExpress.XtraGrid.GridControl.InvalidRowHandle Then
|
If hitInfo.RowHandle = DevExpress.XtraGrid.GridControl.InvalidRowHandle Then
|
||||||
LOGGER.Warn("⚠️ DoubleClick: InvalidRowHandle - ignoring")
|
Dim focused = GridViewWorkflows.FocusedRowHandle
|
||||||
Exit Sub
|
If focused <> DevExpress.XtraGrid.GridControl.InvalidRowHandle Then
|
||||||
|
LOGGER.Debug($"Item_Scope: hitInfo invalid, falling back to FocusedRowHandle [{focused}]")
|
||||||
|
' hitInfo/rowHandle entsprechend neu aufbauen
|
||||||
|
CURRENT_CLICKED_PROFILE_ID = GridViewWorkflows.GetRowCellValue(GridViewWorkflows.GetDataRowHandleByGroupRowHandle(focused), GridViewWorkflows.Columns("PROFILE_ID"))
|
||||||
|
LOGGER.Debug($"Item_Scope: Fallback PROFILE_ID = [{CURRENT_CLICKED_PROFILE_ID}]")
|
||||||
|
|
||||||
|
Else
|
||||||
|
LOGGER.Warn("⚠️ Item_Scope: InvalidRowHandle detected...")
|
||||||
|
Exit Sub
|
||||||
|
End If
|
||||||
End If
|
End If
|
||||||
|
|
||||||
If Not hitInfo.InRow Then
|
If Not hitInfo.InRow Then
|
||||||
@@ -3548,8 +3547,14 @@ Public Class frmMain
|
|||||||
Dim groupRowButtonClicked = (hi.HitTest = GridHitTest.RowGroupButton)
|
Dim groupRowButtonClicked = (hi.HitTest = GridHitTest.RowGroupButton)
|
||||||
' ===== UNGÜLTIGE CLICKS ABFANGEN =====
|
' ===== UNGÜLTIGE CLICKS ABFANGEN =====
|
||||||
If hi.RowHandle = DevExpress.XtraGrid.GridControl.InvalidRowHandle Then
|
If hi.RowHandle = DevExpress.XtraGrid.GridControl.InvalidRowHandle Then
|
||||||
LOGGER.Debug("MouseDown: InvalidRowHandle - ignoring click")
|
Dim focused = GridViewWorkflows.FocusedRowHandle
|
||||||
Exit Sub
|
If focused <> DevExpress.XtraGrid.GridControl.InvalidRowHandle Then
|
||||||
|
LOGGER.Debug($"Item_Scope: hitInfo invalid, falling back to FocusedRowHandle [{focused}]")
|
||||||
|
' hitInfo/rowHandle entsprechend neu aufbauen
|
||||||
|
Else
|
||||||
|
LOGGER.Warn("⚠️ MouseDown: InvalidRowHandle - ignoring click")
|
||||||
|
Exit Sub
|
||||||
|
End If
|
||||||
End If
|
End If
|
||||||
|
|
||||||
If Not hi.InRow Then
|
If Not hi.InRow Then
|
||||||
|
|||||||
Reference in New Issue
Block a user