From 54744a0531029f2fc5d2919672c900a334e01739 Mon Sep 17 00:00:00 2001 From: Developer01 Date: Thu, 26 Feb 2026 10:37:05 +0100 Subject: [PATCH] Vor GridControl Length --- app/TaskFlow/ClassIDBData.vb | 136 +- app/TaskFlow/frmMain.vb | 84 +- app/TaskFlow/frmValidator.vb | 2357 ++++++++++++++++++++-------------- app/TaskFlow/taskFLOW.vbproj | 9 + 4 files changed, 1498 insertions(+), 1088 deletions(-) diff --git a/app/TaskFlow/ClassIDBData.vb b/app/TaskFlow/ClassIDBData.vb index cc44353..89eeecd 100644 --- a/app/TaskFlow/ClassIDBData.vb +++ b/app/TaskFlow/ClassIDBData.vb @@ -1,5 +1,77 @@ Public Class ClassIDBData Public DTVWIDB_BE_ATTRIBUTE As DataTable + Public IDBSystemIndices As List(Of String) + ''' + ''' Wenn True, werden SQL-Statements nicht sofort ausgeführt, + ''' sondern in gesammelt. + ''' + Public Property BatchMode As Boolean = False + Private _sqlBatch As New List(Of String) + + ''' + ''' Startet den Batch-Sammelmodus. + ''' + Public Sub BeginBatch() + _sqlBatch.Clear() + BatchMode = True + End Sub + ''' + ''' Führt alle gesammelten SQL-Statements als einen einzigen String + ''' an ExecuteNonQueryIDB weiter. Jeder Block wird in BEGIN...END + ''' gekapselt, damit DECLARE-Variablen nicht kollidieren. + ''' + ''' True wenn erfolgreich + Public Function CommitBatch() As Boolean + BatchMode = False + If _sqlBatch.Count = 0 Then Return True + Try + Dim oStatements = _sqlBatch. + Where(Function(s) Not String.IsNullOrWhiteSpace(s)). + ToList() + + ' @NEW_OBJ_MD_ID pro Statement eindeutig umbenennen → kein Namenskonflikt im Batch + Dim oNumberedStatements As New List(Of String) + Dim oIndex As Integer = 0 + For Each oStatement As String In oStatements + Dim oNumbered = oStatement.Replace("@NEW_OBJ_MD_ID", $"@NEW_OBJ_MD_ID_{oIndex}") + oNumberedStatements.Add(oNumbered) + oIndex += 1 + Next + + Dim oBatchSQL = String.Join(vbNewLine, oNumberedStatements) + + LOGGER.Debug($"CommitBatch - Executing {oStatements.Count} statements as one batch:{vbNewLine}{oBatchSQL}") + + Dim oResult = DatabaseFallback.ExecuteNonQueryIDB(oBatchSQL) + _sqlBatch.Clear() + Return oResult + Catch ex As Exception + LOGGER.Error(ex) + _sqlBatch.Clear() + Return False + End Try + End Function + + ''' + ''' Verwirft alle gesammelten Statements ohne Ausführung. + ''' + Public Sub RollbackBatch() + _sqlBatch.Clear() + BatchMode = False + End Sub + + ''' + ''' Führt ein SQL-Statement aus – sofort oder gesammelt je nach BatchMode. + ''' + Private Function ExecuteOrQueue(oSQL As String) As Boolean + If BatchMode Then + _sqlBatch.Add(oSQL) + LOGGER.Debug($"BatchMode - Queued statement: {oSQL}") + Return True + Else + Return DatabaseFallback.ExecuteNonQueryIDB(oSQL) + End If + End Function ''' ''' Gets all indices by BusinessEntity. ''' @@ -7,15 +79,16 @@ ''' Array with all Indices ''' ''' - Public Function Init() + Public Function Init() As Boolean Dim oSQL = $"SELECT DISTINCT ATTR_TITLE, TYP_ID, TYP_ID as [TYPE_ID] FROM VWIDB_BE_ATTRIBUTE WHERE SYS_ATTRIBUTE = 0 ORDER BY ATTR_TITLE" DTVWIDB_BE_ATTRIBUTE = DatabaseFallback.GetDatatableIDB(oSQL) If IsNothing(DTVWIDB_BE_ATTRIBUTE) Then oSQL = $"SELECT DISTINCT ATTR_TITLE, TYP_ID, TYP_ID as [TYPE_ID] FROM VWIDB_BE_ATTRIBUTE ORDER BY ATTR_TITLE " DTVWIDB_BE_ATTRIBUTE = DatabaseFallback.GetDatatableIDB(oSQL) End If + Return True End Function - Public IDBSystemIndices As List(Of String) + Public Function GetIndicesByBE(ByVal BusinessEntity As String) As String() Try Dim aNames(4) As String @@ -140,8 +213,9 @@ End If Dim oDELSQL = $"EXEC PRIDB_DELETE_TERM_OBJECT_METADATA {CURRENT_DOC_ID},'{oAttributeName}','{oTerm2Delete}','{USER_USERNAME}','{USER_LANGUAGE}',{oID_IS_FOREIGN}" - DatabaseFallback.ExecuteNonQueryIDB(oDELSQL) - + LOGGER.Debug($"Delete_Term_Object_From_Metadata: {oDELSQL}") + 'DatabaseFallback.ExecuteNonQueryIDB(oDELSQL) + Return ExecuteOrQueue(oDELSQL) Catch ex As Exception LOGGER.Error(ex) Return Nothing @@ -151,8 +225,9 @@ Public Function Delete_AttributeData(pIDB_OBJID As Int64, pAttributeName As String) As Object Try Dim oDELSQL = $"EXEC PRIDB_DELETE_ATTRIBUTE_DATA {pIDB_OBJID},'{pAttributeName}','{USER_USERNAME}'" - DatabaseFallback.ExecuteNonQueryIDB(oDELSQL) - + LOGGER.Debug($"Delete_Attribute_Data: {oDELSQL}") + ' DatabaseFallback.ExecuteNonQueryIDB(oDELSQL) + Return ExecuteOrQueue(oDELSQL) Catch ex As Exception LOGGER.Error(ex) Return Nothing @@ -165,15 +240,15 @@ Dim omytype = oNewValue.GetType.ToString If omytype = "System.Data.DataTable" Then Dim oDTMyNewValues As DataTable = oNewValue - Dim oOldAttributeResult + Dim oAttributeResultFromDB Dim oTypeOldResult If CheckDeleted = True Then - oOldAttributeResult = GetVariableValue(oAttributeName, oIDBTyp) - oTypeOldResult = oOldAttributeResult.GetType.ToString - If oTypeOldResult = "System.Data.DataTable" Then - Dim myOldValues As DataTable = oOldAttributeResult - If myOldValues.Rows.Count > 1 Then + oAttributeResultFromDB = GetVariableValue(oAttributeName, oIDBTyp) + oTypeOldResult = oAttributeResultFromDB.GetType.ToString + If TypeOf oAttributeResultFromDB Is DataTable Then + Dim myOldValues As DataTable = oAttributeResultFromDB + If myOldValues.Rows.Count >= 1 Then 'now Checking whether the old row still remains in Vector? If not it will be deleted as it cannot be replaced in multivalues For Each oOldValueRow As DataRow In myOldValues.Rows @@ -199,27 +274,26 @@ '### Old Value is a single value ### If oDTMyNewValues.Rows.Count > 1 Then '### there is more than one new value ### - Dim oExists As Boolean + Dim oExists As Boolean = False For Each oNewValueRow As DataRow In oDTMyNewValues.Rows - oExists = False - Dim oInfo1 = $"Checking oldValue[{oOldAttributeResult}] vs NewValue [{oNewValueRow.Item(1)}]" - If oNewValueRow.Item(1).ToString.ToUpper = oOldAttributeResult.ToString.ToUpper Then + LOGGER.Debug($"Checking oldValue[{oAttributeResultFromDB}] vs NewValue [{oNewValueRow.Item(1)}]") + If oNewValueRow.Item(1).ToString.ToUpper = oAttributeResultFromDB.ToString.ToUpper Then oExists = True + Exit For ' ← sobald gefunden, abbrechen End If Next If oExists = False Then - Dim oInfo2 = $"Value [{oOldAttributeResult}] no longer existing in Vector-Attribute [{oAttributeName}] - will be deleted!" - LOGGER.Debug(oInfo2) + LOGGER.Debug($"Value [{oAttributeResultFromDB}] no longer existing in Attribute [{oAttributeName}] - will be deleted!") 'SetVariableValue(CURRENT_PROFILE_LOG_INDEX, oInfo2) - Delete_Term_Object_From_Metadata(oAttributeName, oOldAttributeResult) + Delete_Term_Object_From_Metadata(oAttributeName, oAttributeResultFromDB) End If Else '### there is only ONE new value ### - If oDTMyNewValues.Rows(0).Item(1) <> oOldAttributeResult Then - Dim oInfo = $"Value [{oOldAttributeResult}] of Attribute [{oAttributeName}] obviously was updated during runtime - will be deleted!" + If oDTMyNewValues.Rows(0).Item(1) <> oAttributeResultFromDB Then + Dim oInfo = $"Value [{oAttributeResultFromDB}] of Attribute [{oAttributeName}] obviously was updated during runtime - will be deleted!" LOGGER.Debug(oInfo) SetVariableValue(CURRENT_PROFILE_LOG_INDEX, oInfo) - Delete_Term_Object_From_Metadata(oAttributeName, oOldAttributeResult) + Delete_Term_Object_From_Metadata(oAttributeName, oAttributeResultFromDB) Else LOGGER.Debug($"Attributvalue of [{oAttributeName}] did not change!") End If @@ -231,22 +305,24 @@ End If For Each oNewValueRow As DataRow In oDTMyNewValues.Rows - Dim oSuccess As Boolean = False + 'Dim oSuccess As Boolean = False Dim oVALUE = oNewValueRow.Item(1).ToString oVALUE = oVALUE.Replace("'", "''") Dim oPRSQL = $"DECLARE @NEW_OBJ_MD_ID BIGINT " & vbNewLine & $"EXEC PRIDB_NEW_OBJ_DATA {CURRENT_DOC_ID},'{oAttributeName}','{USER_USERNAME}','{oVALUE}','{USER_LANGUAGE}',0,@OMD_ID = @NEW_OBJ_MD_ID OUTPUT" LOGGER.Debug(oPRSQL) - oSuccess = DatabaseFallback.ExecuteNonQueryIDB(oPRSQL) - If oSuccess = False Then - Return False - End If + 'oSuccess = DatabaseFallback.ExecuteNonQueryIDB(oPRSQL) + If Not ExecuteOrQueue(oPRSQL) Then Return False + 'If oSuccess = False Then + ' Return False + 'End If Next Return True Else 'oNewValue = oNewValue.Replace("'", "' + NCHAR(39) + '") - Dim oFNSQL = $"DECLARE @NEW_OBJ_MD_ID BIGINT " & vbNewLine & $"EXEC PRIDB_NEW_OBJ_DATA {CURRENT_DOC_ID},'{oAttributeName}','{USER_USERNAME}','{oNewValue}','{USER_LANGUAGE}',0,@OMD_ID = @NEW_OBJ_MD_ID OUTPUT" - LOGGER.Debug(oFNSQL) - Return DatabaseFallback.ExecuteNonQueryIDB(oFNSQL) + Dim oPRIDB_NEW_OBJ_DATA = $"DECLARE @NEW_OBJ_MD_ID BIGINT " & vbNewLine & $"EXEC PRIDB_NEW_OBJ_DATA {CURRENT_DOC_ID},'{oAttributeName}','{USER_USERNAME}','{oNewValue}','{USER_LANGUAGE}',0,@OMD_ID = @NEW_OBJ_MD_ID OUTPUT" + LOGGER.Debug(oPRIDB_NEW_OBJ_DATA) + ' Return DatabaseFallback.ExecuteNonQueryIDB(oPRIDB_NEW_OBJ_DATA) + Return ExecuteOrQueue(oPRIDB_NEW_OBJ_DATA) End If Catch ex As Exception diff --git a/app/TaskFlow/frmMain.vb b/app/TaskFlow/frmMain.vb index ef6311a..772aa7e 100644 --- a/app/TaskFlow/frmMain.vb +++ b/app/TaskFlow/frmMain.vb @@ -15,6 +15,7 @@ Imports DevExpress.XtraGrid.Views.Grid Imports DevExpress.XtraGrid.Views.Grid.ViewInfo Imports DevExpress.XtraNavBar Imports DevExpress.XtraPrinting +Imports DevExpress.XtraSplashScreen Imports DigitalData.GUIs.Common Imports DigitalData.Modules.Base Imports DigitalData.Modules.EDMI.API.Constants @@ -61,6 +62,7 @@ Public Class frmMain Private DetailLinkActive As Boolean = False Private FRONTEND_ACTION As String = "NONE" Private Ev_Filter_Panel_Closed As Boolean = False + Private _overlayActive As Boolean = False Dim omsgOpenWorkflow As String Dim omsgTitleWarning As String @@ -1398,6 +1400,13 @@ Public Class frmMain ' HAUPTLADEMETHODE - Koordiniert den gesamten Ladevorgang ' ======================================== Private Async Function Decide_Load(pIsFormLoad As Boolean, Optional ForceReload As Boolean = False) As Tasks.Task + Dim oHandle As Object = Nothing + Dim overlayStartedHere As Boolean = False + If Not _overlayActive Then + oHandle = SplashScreenManager.ShowOverlayForm(Me) + _overlayActive = True + overlayStartedHere = True + End If Dim perfStart As DateTime = DateTime.MinValue Dim refreshWasEnabled As Boolean = False @@ -1436,10 +1445,10 @@ Public Class frmMain LOGGER.Info("[PERF Decide_Load] ruft LoadOverviewData auf...") End If - ' UI vorbereiten - If Not PrepareGridForLoading() Then - Exit Function - End If + '' UI vorbereiten + 'If Not PrepareGridForLoading() Then + ' Exit Function + 'End If Await Task.Yield() @@ -1451,10 +1460,10 @@ Public Class frmMain LOGGER.Info("[PERF Decide_Load] ruft LoadProfileData auf...") End If - ' UI vorbereiten - If Not PrepareGridForLoading() Then - Exit Function - End If + '' UI vorbereiten + 'If Not PrepareGridForLoading() Then + ' Exit Function + 'End If Await Task.Yield() @@ -1477,7 +1486,10 @@ Public Class frmMain LOGGER.Info("Unexpected error in Decide_load: " & ex.Message) Finally FRONTEND_ACTION = FA_NONE - + If overlayStartedHere Then + _overlayActive = False + SplashScreenManager.CloseOverlayForm(oHandle) + End If If refreshWasEnabled Then TimerRefresh.Start() End If @@ -1491,33 +1503,6 @@ Public Class frmMain End If End Try End Function - - ' ======================================== - ' UI-VORBEREITUNG - Macht Grid sichtbar und zeigt LoadingPanel - ' ======================================== - Private Function PrepareGridForLoading() As Boolean - Try - ' Grid sichtbar machen - If GridControlWorkflows.Visible = False Then - GridControlWorkflows.Visible = True - End If - - ' UI-Thread Zeit geben - Application.DoEvents() - - ' LoadingPanel anzeigen - GridViewWorkflows.ShowLoadingPanel() - - ' Nochmal Zeit zum Rendern - Application.DoEvents() - - Return True - Catch ex As Exception - LOGGER.Error(ex) - Return False - End Try - End Function - ' ======================================== ' OVERVIEW DATEN LADEN - Spezialisiert auf Overview ' ======================================== @@ -1686,9 +1671,6 @@ Public Class frmMain GridControlWorkflows.EndUpdate() End If - ' LoadingPanel verstecken (NUR HIER!) - GridViewWorkflows.HideLoadingPanel() - If LOG_HOTSPOTS Then Dim totalElapsed = (DateTime.Now - perfStart).TotalMilliseconds If totalElapsed > 4000 Then @@ -1759,9 +1741,6 @@ Public Class frmMain If gridUpdateStarted Then GridControlWorkflows.EndUpdate() End If - - ' LoadingPanel verstecken (NUR HIER!) - GridViewWorkflows.HideLoadingPanel() End Try End Function @@ -2548,11 +2527,9 @@ Public Class frmMain Dim viewUpdateStarted As Boolean = False Dim layoutRestored As Boolean = False Dim resetLayoutTriggered As Boolean = False - Dim showLoadingPanel As Boolean = False Dim useWaitCursorApplied As Boolean = False Dim previousMessage As String = bsiMessage.Caption Dim loadingMessageApplied As Boolean = False - Dim gridWasMadeVisible As Boolean = False If LOG_HOTSPOTS Then perfStart = DateTime.Now @@ -2564,24 +2541,11 @@ Public Class frmMain ' SCHRITT 1: Grid sichtbar machen If GridControlWorkflows.Visible = False Then GridControlWorkflows.Visible = True - gridWasMadeVisible = True End If GRID_LOAD_TYPE = "OVERVIEW" CURRENT_CLICKED_PROFILE_ID = 0 - ' SCHRITT 2: UI-Thread Zeit geben, das Grid zu rendern - Application.DoEvents() - Await Task.Delay(100) - - ' SCHRITT 3: LoadingPanel anzeigen (jetzt ist das Grid definitiv sichtbar!) - GridViewWorkflows.ShowLoadingPanel() - showLoadingPanel = True - - ' SCHRITT 4: UI-Thread Zeit zum Rendern des LoadingPanels geben - Application.DoEvents() - Await Task.Delay(150) - If LOG_HOTSPOTS Then Dim elapsed = (DateTime.Now - perfStep).TotalMilliseconds If elapsed > 4000 Then @@ -2876,7 +2840,6 @@ Public Class frmMain Finally ' ========== AUFRÄUMEN ========== - ' EndUpdate IMMER aufrufen (vor dem Verstecken des LoadingPanel) If viewUpdateStarted Then GridViewWorkflows.EndUpdate() End If @@ -2884,11 +2847,6 @@ Public Class frmMain GridControlWorkflows.EndUpdate() End If - ' LoadingPanel SOFORT nach EndUpdate verstecken - If showLoadingPanel Then - GridViewWorkflows.HideLoadingPanel() - End If - ' WaitCursor entfernen If useWaitCursorApplied Then Me.UseWaitCursor = False diff --git a/app/TaskFlow/frmValidator.vb b/app/TaskFlow/frmValidator.vb index ccd6a1c..931acc8 100644 --- a/app/TaskFlow/frmValidator.vb +++ b/app/TaskFlow/frmValidator.vb @@ -8,6 +8,7 @@ Imports System.Reflection Imports System.Runtime.InteropServices Imports System.Text.RegularExpressions Imports System.Threading +Imports DevExpress.Data Imports DevExpress.DataAccess.Native.Sql Imports DevExpress.DataProcessing.InMemoryDataProcessor Imports DevExpress.Utils @@ -21,6 +22,7 @@ Imports DevExpress.XtraGrid Imports DevExpress.XtraGrid.Columns Imports DevExpress.XtraGrid.Views.Base Imports DevExpress.XtraGrid.Views.Grid +Imports DevExpress.XtraSplashScreen Imports DigitalData.Controls.LookupGrid Imports DigitalData.GUIs.Common Imports DigitalData.GUIs.Common.DocumentResultList @@ -133,6 +135,7 @@ Public Class frmValidator Private _CachedControlsByGuid As Dictionary(Of Integer, Control) Private _isUpdatingLookup As Boolean = False Private _suppressLookupEvents As Boolean = False + Private _overlayActive As Boolean = False Private Class Translation_Strings Inherits My.Resources.frmValidator_Strings End Class @@ -582,137 +585,165 @@ Public Class frmValidator MyValidationLogger.Info("Unexpected error in LOADING Profile-Data1: " & ex.Message) End Try End Sub - + Private _isClosingGuard As Boolean = False Private Sub frmValidation_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing - If LOG_HOTSPOTS Then - ' ========== DIAGNOSE: Wer schließt die Form? ========== - MyValidationLogger.Warn($" frmValidator_FormClosing aufgerufen!") - MyValidationLogger.Warn($" CloseReason: {e.CloseReason}") - MyValidationLogger.Warn($" Cancel: {e.Cancel}") - - ' *** KORREKTUR: StackTrace richtig erstellen *** - Dim st As New StackTrace(True) - MyValidationLogger.Warn($" StackTrace: {st.ToString()}") - - ' Zusätzliche Diagnostik - MyValidationLogger.Warn($" _FormClosing-Flag: {_FormClosing}") - MyValidationLogger.Warn($" CURRENT_DOC_GUID: {CURRENT_DOC_GUID}") - MyValidationLogger.Warn($" CURRENT_ProfilGUID: {CURRENT_ProfilGUID}") - ' ========== ENDE DIAGNOSE ========== - End If - - Dim perfStart As DateTime = DateTime.MinValue - Dim perfLastCheck As DateTime = DateTime.MinValue - If LOG_HOTSPOTS Then - perfStart = DateTime.Now - perfLastCheck = perfStart - MyValidationLogger.Info("[PERF frmValidation_FormClosing] START") + ' ========== FIX 4: Re-Entry-Guard (Klassenfeld statt Static) ========== + If _isClosingGuard Then + MyValidationLogger.Warn("[FormClosing] Bereits aktiv → Exit Sub (Re-Entry verhindert)") + Return End If + _isClosingGuard = True + ' ========== ENDE FIX 4 ========== Try + If LOG_HOTSPOTS Then + ' ========== DIAGNOSE: Wer schließt die Form? ========== + MyValidationLogger.Warn($" frmValidator_FormClosing aufgerufen!") + MyValidationLogger.Warn($" CloseReason: {e.CloseReason}") + MyValidationLogger.Warn($" Cancel: {e.Cancel}") + + ' *** KORREKTUR: StackTrace richtig erstellen *** + Dim st As New StackTrace(True) + MyValidationLogger.Warn($" StackTrace: {st.ToString()}") + + ' Zusätzliche Diagnostik + MyValidationLogger.Warn($" _FormClosing-Flag: {_FormClosing}") + MyValidationLogger.Warn($" CURRENT_DOC_GUID: {CURRENT_DOC_GUID}") + MyValidationLogger.Warn($" CURRENT_ProfilGUID: {CURRENT_ProfilGUID}") + ' ========== ENDE DIAGNOSE ========== + End If + + Dim perfStart As DateTime = DateTime.MinValue + Dim perfLastCheck As DateTime = DateTime.MinValue + If LOG_HOTSPOTS Then + perfStart = DateTime.Now + perfLastCheck = perfStart + MyValidationLogger.Info("[PERF frmValidation_FormClosing] START") + End If + _FormClosing = True - If Application.OpenForms().OfType(Of frmValidator_Messages).Any Then - If Not IsNothing(frmMessages) Then - frmMessages.Close() + ' ========== FIX 5: Sichere Prüfung für frmMessages ========== + If Not Me.IsDisposed AndAlso Application.OpenForms().OfType(Of frmValidator_Messages).Any Then + If Not IsNothing(frmMessages) AndAlso Not frmMessages.IsDisposed Then + Try + frmMessages.Close() + Catch ex As Exception + MyValidationLogger.Warn($"[FormClosing] frmMessages.Close() failed: {ex.Message}") + End Try End If End If + ' ========== ENDE FIX 5 ========== If LOG_HOTSPOTS Then MyValidationLogger.Info($"[PERF frmValidation_FormClosing] nach Messages-Close: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") perfLastCheck = DateTime.Now End If - Try - ' Position und Größe speichern - My.Settings.frmValidatorSize = Me.Size - My.Settings.frmValidatorPosition = Me.Location - My.Settings.Save() - Catch ex As Exception - MyValidationLogger.Error(ex) - MyValidationLogger.Info("Error in Load FormLayout: " & ex.Message) - End Try + ' ========== FIX 6: Settings nur bei nicht-disposed Form ========== + If Not Me.IsDisposed Then + Try + ' Position und Größe speichern + My.Settings.frmValidatorSize = Me.Size + My.Settings.frmValidatorPosition = Me.Location + My.Settings.frmValidatorWindowState = If(Me.WindowState = FormWindowState.Maximized, "Maximized", "Normal") + My.Settings.Save() + Catch ex As Exception + MyValidationLogger.Warn($"[FormClosing] Settings.Save() failed: {ex.Message}") + MyValidationLogger.Error(ex) + End Try + End If + ' ========== ENDE FIX 6 ========== If LOG_HOTSPOTS Then MyValidationLogger.Info($"[PERF frmValidation_FormClosing] nach Settings.Save: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") perfLastCheck = DateTime.Now End If - My.Settings.frmValidatorSize = Me.Size - My.Settings.Save() - + ' ========== FIX 7: Inactivity Timer ========== If INACTIVITY_DURATION <> 0 Then - frmMain.Timer_Inactivity_Reset_Disable("FormClosing") + Try + frmMain.Timer_Inactivity_Reset_Disable("FormClosing") + Catch ex As Exception + MyValidationLogger.Warn($"[FormClosing] Timer_Inactivity failed: {ex.Message}") + End Try End If + ' ========== ENDE FIX 7 ========== If LOG_HOTSPOTS Then MyValidationLogger.Info($"[PERF frmValidation_FormClosing] nach Timer-Reset: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") perfLastCheck = DateTime.Now End If - Catch ex As Exception - MyValidationLogger.Error(ex) - End Try - - Try - Dim oSQL As String - If CURRENT_DOC_GUID <> 0 Then - Dim oPRoc = String.Format("EXEC PRTF_PROFILE_FILES_WORK {0},{1},{2},'FreeFile'", CURRENT_DOC_ID, CURRENT_ProfilGUID, USER_ID) - oSQL = $"DELETE FROM TBPM_DOCWALKOVER WHERE UserID = {USER_ID};" & vbNewLine & - oPRoc - Else - oSQL = $"DELETE FROM TBPM_DOCWALKOVER WHERE UserID = {USER_ID};" - End If + ' ========== FIX 8: DB Cleanup ========== + Try + Dim oSQL As String + If CURRENT_DOC_GUID <> 0 Then + Dim oPRoc = String.Format("EXEC PRTF_PROFILE_FILES_WORK {0},{1},{2},'FreeFile'", CURRENT_DOC_ID, CURRENT_ProfilGUID, USER_ID) + oSQL = $"DELETE FROM TBPM_DOCWALKOVER WHERE UserID = {USER_ID};" & vbNewLine & oPRoc + Else + oSQL = $"DELETE FROM TBPM_DOCWALKOVER WHERE UserID = {USER_ID};" + End If - DatabaseFallback.ExecuteNonQueryECM(oSQL) + DatabaseFallback.ExecuteNonQueryECM(oSQL) + Catch ex As Exception + MyValidationLogger.Error(ex) + MsgBox("Error in delete jumped files:" & vbNewLine & ex.Message, MsgBoxStyle.Critical) + End Try + ' ========== ENDE FIX 8 ========== If LOG_HOTSPOTS Then MyValidationLogger.Info($"[PERF frmValidation_FormClosing] nach DB-Cleanup: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") perfLastCheck = DateTime.Now End If - Catch ex As Exception - MyValidationLogger.Error(ex) - MsgBox("Error in delete jumped files:" & vbNewLine & ex.Message, MsgBoxStyle.Critical) - End Try - - Reset_CurrentReferences() - - If LOG_HOTSPOTS Then - MyValidationLogger.Info($"[PERF frmValidation_FormClosing] nach Reset_CurrentReferences: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") - perfLastCheck = DateTime.Now - End If + Reset_CurrentReferences() - Try - If Not IsNothing(DocumentViewer1) Then - DocumentViewer1.CloseDocument() - DocumentViewer1.Done() + If LOG_HOTSPOTS Then + MyValidationLogger.Info($"[PERF frmValidation_FormClosing] nach Reset_CurrentReferences: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") + perfLastCheck = DateTime.Now End If + ' ========== FIX 9: DocumentViewer cleanup ========== + Try + If Not IsNothing(DocumentViewer1) AndAlso Not DocumentViewer1.IsDisposed Then + DocumentViewer1.CloseDocument() + DocumentViewer1.Done() + End If + Catch ex As Exception + MyValidationLogger.Warn($"Unexpected error in DocumentViewerValidator.Done: {ex.Message}") + End Try + ' ========== ENDE FIX 9 ========== + If LOG_HOTSPOTS Then MyValidationLogger.Info($"[PERF frmValidation_FormClosing] nach DocumentViewer.Done: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") perfLastCheck = DateTime.Now End If - Catch ex As Exception - MyValidationLogger.Warn($"Unexpected error in DocumentViewerValidator.Done: {ex.Message}") - End Try - - Try - _frmValidatorSearch.Close() + ' ========== FIX 10: ValidatorSearch cleanup ========== + Try + If _frmValidatorSearch IsNot Nothing AndAlso Not _frmValidatorSearch.IsDisposed Then + _frmValidatorSearch.Close() + End If + Catch ex As Exception + MyValidationLogger.Error(ex) + End Try + ' ========== ENDE FIX 10 ========== If LOG_HOTSPOTS Then MyValidationLogger.Info($"[PERF frmValidation_FormClosing] nach ValidatorSearch.Close: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") perfLastCheck = DateTime.Now End If - Catch ex As Exception - MyValidationLogger.Error(ex) - End Try + If LOG_HOTSPOTS Then + MyValidationLogger.Info($"[PERF frmValidation_FormClosing] GESAMT: {(DateTime.Now - perfStart).TotalMilliseconds}ms") + End If - If LOG_HOTSPOTS Then - MyValidationLogger.Info($"[PERF frmValidation_FormClosing] GESAMT: {(DateTime.Now - perfStart).TotalMilliseconds}ms") - End If + Finally + ' WICHTIG: Guard wird NICHT zurückgesetzt, da die Form nun wirklich schließt. + ' Ein Reset würde den erneuten BeginInvoke-Close wieder durchlassen. + ' _isClosingGuard = False ← absichtlich NICHT zurückgesetzt + End Try End Sub Sub Reset_CurrentReferences() If Not IsNothing(DT_AdditionalSearches_Resultset_Docs) Then @@ -928,9 +959,54 @@ Public Class frmValidator Try Dim lookup As LookupControl3 = control + ' ========== BUGFIX: Wert SICHERN bevor DataSource überschrieben wird ========== + Dim previousSelectedValues As List(Of String) = Nothing + + ' Aber ACHTUNG: Nur sichern, wenn bereits Werte gesetzt sind! + If lookup.Properties.SelectedValues IsNot Nothing AndAlso lookup.Properties.SelectedValues.Count > 0 Then + ' Hier KÖNNEN Werte drin sein (z.B. "4711" aus FillIndexValues) + previousSelectedValues = New List(Of String)(lookup.Properties.SelectedValues) + MyValidationLogger.Debug($"[LoadSQLData BUGFIX] Alte SelectedValues gesichert: [{String.Join(",", previousSelectedValues)}]") + End If + + ' DataSource MIT NEUEM DataTable ÜBERSCHREIBEN (das ist der "Fehler") lookup.Properties.DataSource = oDTContent lookup.Properties.ValueMember = oDTContent.Columns.Item(0).ColumnName lookup.Properties.DisplayMember = oDTContent.Columns.Item(0).ColumnName + + ' ========== CRITICAL: Nach DataSource-Zuweisung sind SelectedValues GELÖSCHT! ========== + ' Daher müssen wir sie WIEDERHERSTELLEN: + If previousSelectedValues IsNot Nothing AndAlso previousSelectedValues.Count > 0 Then + ' Nur wiederherstellen wenn: + ' 1. Wir vorher Werte gesichert haben UND + ' 2. Die Werte im NEUEN DataSource existieren + + ' Optional: Validierung dass Werte noch im neuen DataSource vorhanden sind + Dim newDataSource As DataTable = lookup.Properties.DataSource + Dim validValues As New List(Of String) + + For Each oldValue As String In previousSelectedValues + ' Prüfe ob oldValue im neuen DataSource existiert + Dim exists = newDataSource.AsEnumerable(). + Any(Function(r) r.Item(0).ToString = oldValue) + + If exists Then + validValues.Add(oldValue) + MyValidationLogger.Debug($"[LoadSQLData BUGFIX] Wert [{oldValue}] existiert im neuen DataSource ✓") + Else + MyValidationLogger.Warn($"[LoadSQLData BUGFIX] Wert [{oldValue}] existiert NICHT im neuen DataSource ✗") + End If + Next + + ' Nur wenn noch gültige Werte übrig sind + If validValues.Count > 0 Then + lookup.Properties.SelectedValues = validValues + MyValidationLogger.Debug($"[LoadSQLData BUGFIX] SelectedValues wiederhergestellt: [{String.Join(",", validValues)}]") + Else + MyValidationLogger.Warn($"[LoadSQLData BUGFIX] Keine Werte zum Wiederherstellen vorhanden!") + End If + End If + Catch ex As Exception MyValidationLogger.Warn("⚠️ Error in LookUpLoadSQLData: " & ex.Message) End Try @@ -949,6 +1025,9 @@ Public Class frmValidator ElseIf TypeOf control Is Windows.Forms.ComboBox Then Try Dim oMyComboBox As Windows.Forms.ComboBox = control + ' Aktuellen TEXT sichern (nicht Index – der kann nach Refresh an anderer Position sein) + Dim previousText As String = oMyComboBox.Text + Dim oselectedIndex = oMyComboBox.SelectedIndex MyValidationLogger.Debug($"oMyComboBox {oMyComboBox.Name} - Saving selected index {oselectedIndex}") Dim list As New List(Of String) @@ -1143,7 +1222,7 @@ Public Class frmValidator oCONID = 0 End Try - If oCONID > 0 Then + If oCONID >= 0 Then Dim oCommandSQL_UBPF Try oCommandSQL_UBPF = oControlRow.Item("SQL_UEBERPRUEFUNG") @@ -1151,7 +1230,7 @@ Public Class frmValidator oCommandSQL_UBPF = "" End Try MyValidationLogger.Debug("ConID <> String.Empty") - If oCONID > 0 And oCommandSQL_UBPF <> String.Empty Then + If oCommandSQL_UBPF <> String.Empty Then MyValidationLogger.Debug("ConID > 0 And commandsql <> String.Empty") Try oSQL = PreventNulletc(oControlRow.Item("SQL_UEBERPRUEFUNG"), "String") @@ -1278,7 +1357,7 @@ Public Class frmValidator MyValidationLogger.Debug($"createControlsLU - Found {oFilteredData.Rows.Count} Controls which are depending on {oMyControl.Name}") AddHandler MyLookupControl.Properties.SelectedValuesChanged, AddressOf onLookUpselectedValue End If - + oFilteredData = DT_CONTROLS.Clone() oExpression = $"SQL_ENABLE like '%#CTRL#{oMyControl.Name}%'" DT_CONTROLS.Select(oExpression).CopyToDataTable(oFilteredData, LoadOption.PreserveChanges) If oFilteredData.Rows.Count >= 1 Then @@ -1333,6 +1412,9 @@ Public Class frmValidator oMyControl = oGrid ' NEU: GridView Event registrieren AddHandler DirectCast(oGrid.MainView, GridView).CellValueChanged, AddressOf GridView_CellValueChanged + AddHandler DirectCast(oGrid.DataSource, DataTable).RowDeleted, AddressOf GridDataSource_RowDeleted + AddHandler DirectCast(oGrid.MainView, GridView).KeyDown, AddressOf GridView_KeyDown + AddHandler DirectCast(oGrid.MainView, GridView).RowDeleting, AddressOf GridView_RowDeleting Case "LINE" oMyControl = ControlCreator.CreateExistingLine(oControlRow, False) @@ -1765,7 +1847,9 @@ Public Class frmValidator Public Sub onLookUpselectedValue(sender As Object, SelectedValues As List(Of String)) Try MyValidationLogger.Debug("onLookUpselectedValue") + ' *** GLOBALER GUARD: Bei Refresh KOMPLETT blockieren *** If _FormLoaded = False Or _suppressLookupEvents Then + MyValidationLogger.Debug("onLookUpselectedValue suppressed (global guard active)") Exit Sub End If @@ -1892,6 +1976,163 @@ Public Class frmValidator oMeta.IsDirty = True MyValidationLogger.Debug($"GridControl [{oMeta.Name}] marked as dirty (Row {e.RowHandle}, Col {e.Column.FieldName})") End Sub + Private Sub GridDataSource_RowDeleted(sender As Object, e As DataRowChangeEventArgs) + If Me.IsDisposed OrElse _FormClosing Then Exit Sub + Try + ' DataSource → GridControl finden + Dim oDataTable As DataTable = DirectCast(sender, DataTable) + For Each oControl As Control In PanelValidatorControl.Controls + If TypeOf oControl Is GridControl Then + Dim oGrid As GridControl = DirectCast(oControl, GridControl) + If oGrid.DataSource Is oDataTable Then + Dim oMeta As ClassControlCreator.ControlMetadata = TryCast(oGrid.Tag, ClassControlCreator.ControlMetadata) + If oMeta IsNot Nothing Then + oMeta.IsDirty = True + MyValidationLogger.Debug($"GridControl [{oMeta.Name}] marked as dirty (RowDeleted via DataSource)") + End If + Exit For + End If + End If + Next + Catch ex As Exception + MyValidationLogger.Warn($"GridDataSource_RowDeleted: {ex.Message}") + End Try + End Sub + + ' ========== NEU: Cleanup-Methode für gelöschte Zeilen ========== + ''' + ''' Entfernt physisch alle Zeilen mit RowState = Deleted aus dem DataTable. + ''' WICHTIG: Muss VOR der Validierung aufgerufen werden! + ''' + Private Sub CleanupDeletedRows(pGrid As GridControl) + Try + MyValidationLogger.Debug($"[6] CleanupDeletedRows START für Grid: [{pGrid.Name}]") + Dim oDataSource As DataTable = TryCast(pGrid.DataSource, DataTable) + If oDataSource Is Nothing Then Return + + ' Alle gelöschten Zeilen sammeln + Dim deletedRows = oDataSource.Rows.Cast(Of DataRow)(). + Where(Function(r) r.RowState = DataRowState.Deleted). + ToList() + + If deletedRows.Count > 0 Then + MyValidationLogger.Debug($"Grid [{pGrid.Name}]: Entferne {deletedRows.Count} gelöschte Zeilen aus DataSource") + + ' Zeilen PHYSISCH entfernen (nicht nur markieren!) + For Each row In deletedRows + oDataSource.Rows.Remove(row) + Next + + ' AcceptChanges → alle RowState-Flags zurücksetzen + oDataSource.AcceptChanges() + End If + Catch ex As Exception + MyValidationLogger.Warn($"CleanupDeletedRows: {ex.Message}") + End Try + End Sub + ' ========== ENDE NEU ========== + Private Sub GridView_KeyDown(sender As Object, e As KeyEventArgs) + If Me.IsDisposed OrElse _FormClosing Then Exit Sub + If e.KeyCode <> Keys.Delete Then Exit Sub + MyValidationLogger.Debug($"[GridView_KeyDown] DEL-Taste gedrückt!") + Try + Dim oView As GridView = DirectCast(sender, GridView) + + ' Nur löschen wenn eine gültige Zeile fokussiert ist + If oView.FocusedRowHandle < 0 Then Exit Sub + ' Nicht löschen wenn eine Zelle gerade bearbeitet wird + If oView.ActiveEditor IsNot Nothing Then Exit Sub + + Dim oGrid As GridControl = oView.GridControl + Dim oMeta As ClassControlCreator.ControlMetadata = TryCast(oGrid.Tag, ClassControlCreator.ControlMetadata) + If oMeta IsNot Nothing Then + oMeta.IsDirty = True + MyValidationLogger.Debug($"[GridView_KeyDown] Grid [{oMeta.Name}] marked as dirty") + End If + + Dim oDataSource As DataTable = TryCast(oGrid.DataSource, DataTable) + If oDataSource Is Nothing Then Exit Sub + + ' Mehrsprachige Texte abhängig von USER_LANGUAGE + Dim oQuestion As String + Dim oTitle As String + Select Case USER_LANGUAGE + Case "de-DE" + oQuestion = "Möchten Sie die markierte Zeile wirklich löschen?" + oTitle = "Zeile löschen" + Case "fr-FR" + oQuestion = "Voulez-vous vraiment supprimer la ligne sélectionnée?" + oTitle = "Supprimer la ligne" + Case Else ' en-US, en-GB, etc. + oQuestion = "Do you really want to delete the selected row?" + oTitle = "Delete row" + End Select + + Dim oResult = MessageBox.Show( + oQuestion, + oTitle, + MessageBoxButtons.YesNo, + MessageBoxIcon.Question) + + If oResult = DialogResult.Yes Then + Dim oDataSource1 As DataTable = TryCast(oGrid.DataSource, DataTable) + If oDataSource1 IsNot Nothing Then + Dim oRowIndex = oView.GetDataSourceRowIndex(oView.FocusedRowHandle) + If oRowIndex >= 0 AndAlso oRowIndex < oDataSource.Rows.Count Then + ' ========== KRITISCHE ÄNDERUNG ========== + oDataSource.Rows(oRowIndex).Delete() ' ← Statt RemoveAt() + ' ========== ENDE ÄNDERUNG ========== + + MyValidationLogger.Debug($"GridControl [{oGrid.Name}] - Row {oRowIndex} marked as DELETED (RowState)") + End If + End If + End If + + e.Handled = True + Catch ex As Exception + MyValidationLogger.Warn($"GridView_KeyDown (Delete): {ex.Message}") + End Try + End Sub + Private Sub GridView_RowDeleting(sender As Object, e As RowDeletingEventArgs) + If Me.IsDisposed OrElse _FormClosing Then Exit Sub + + ' Guard: Nur gültige Zeilen verarbeiten + If e.RowHandle < 0 Then Exit Sub + + Try + Dim oView As GridView = DirectCast(sender, GridView) + Dim oGrid As GridControl = oView.GridControl + + Dim oMeta As ClassControlCreator.ControlMetadata = TryCast(oGrid.Tag, ClassControlCreator.ControlMetadata) + If oMeta IsNot Nothing Then + oMeta.IsDirty = True + MyValidationLogger.Debug($"[GridView_RowDeleting] Grid [{oMeta.Name}] marked as dirty") + End If + + Dim oDataSource As DataTable = TryCast(oGrid.DataSource, DataTable) + If oDataSource Is Nothing Then Exit Sub + + Dim oRowIndex = oView.GetDataSourceRowIndex(e.RowHandle) + If oRowIndex >= 0 AndAlso oRowIndex < oDataSource.Rows.Count Then + Dim oRow As DataRow = oDataSource.Rows(oRowIndex) + + ' Guard: Nur löschen wenn noch nicht als Deleted markiert + If oRow.RowState = DataRowState.Deleted Then + MyValidationLogger.Debug($"[GridView_RowDeleting] Row {oRowIndex} bereits als DELETED markiert - übersprungen") + e.Cancel = True + Return + End If + + oRow.Delete() + MyValidationLogger.Debug($"[GridView_RowDeleting] Grid [{oGrid.Name}] - Row {oRowIndex} marked as DELETED (RowState)") + End If + + e.Cancel = True + oView.RefreshData() + Catch ex As Exception + MyValidationLogger.Warn($"GridView_RowDeleting: {ex.Message}") + End Try + End Sub Public Sub onCheckBox_CheckedChange(sender As Object, e As EventArgs) MyValidationLogger.Debug("onCheckBox_CheckedChange") @@ -1928,6 +2169,17 @@ Public Class frmValidator End Sub Private Sub SetControlValues_FromControl(pControl As Control) + ' *** KRITISCH: Während FillIndexValues BLOCKIEREN! *** + If _suppressLookupEvents Then + MyValidationLogger.Debug("SetControlValues_FromControl -> BLOCKED by _suppressLookupEvents (FillIndexValues läuft)") + Exit Sub + End If + ' Prevent re-entry + If _SetControlValue_In_Action Then + MyValidationLogger.Debug("SetControlValues_FromControl -> SetControlValue in action. Exiting.") + Exit Sub + End If + Dim oControlName = pControl.Name Dim oControlMeta = DirectCast(pControl.Tag, ClassControlCreator.ControlMetadata) Dim oControlID = oControlMeta.Guid @@ -2540,93 +2792,93 @@ Public Class frmValidator End Sub Private Sub Controls2beEnabled(pControlName As String) Try - ' 18.10.2021: ENABLE_SQL nicht beim Form Load verarbeiten If _FormLoaded = False Then Exit Sub End If - Dim oFilteredDatatable As DataTable = DT_CONTROLS.Clone() - Dim oExpression = $"SQL_ENABLE like '%#CTRL#{pControlName}%'" - DT_CONTROLS.Select(oExpression).CopyToDataTable(oFilteredDatatable, LoadOption.PreserveChanges) - If oFilteredDatatable.Rows.Count > 0 Then - MyValidationLogger.Debug($"We got {oFilteredDatatable.Rows.Count} controls which got enable definitions!!") - Else + ' Controls mit SQL_ENABLE-Definition ermitteln: + ' 1. Controls, deren SQL_ENABLE den auslösenden Control-Namen referenziert (#CTRL#Name) + ' 2. Controls, deren SQL_ENABLE keinen #CTRL#-Platzhalter hat (statische SQL, z.B. für Buttons) + Dim enablingRows = DT_CONTROLS.AsEnumerable(). + Where(Function(r) + Dim sql = r.ItemEx("SQL_ENABLE", String.Empty).ToString() + If String.IsNullOrEmpty(sql) Then Return False + Return sql.Contains($"#CTRL#{pControlName}") OrElse Not sql.Contains("#CTRL#") + End Function). + ToList() + + If enablingRows.Count = 0 Then MyValidationLogger.Debug($"Sorry NO controls with enabling definition!!") + Return End If - For Each oRowEnablingControl As DataRow In oFilteredDatatable.Rows - Dim oENABLE_GUID = oRowEnablingControl.Item("GUID") + + MyValidationLogger.Debug($"We got {enablingRows.Count} controls which got enable definitions!!") + + ' ========== OPTIMIERUNG: Dictionary-Lookup statt Panel-Loop ========== + If _CachedControlsByGuid Is Nothing Then + _CachedControlsByGuid = New Dictionary(Of Integer, Control)() + For Each ctrl As Control In PanelValidatorControl.Controls + Try + Dim meta = DirectCast(ctrl.Tag, ClassControlCreator.ControlMetadata) + _CachedControlsByGuid(meta.Guid) = ctrl + Catch + Continue For + End Try + Next + End If + ' ========== ENDE OPTIMIERUNG ========== + + For Each oRowEnablingControl As DataRow In enablingRows + + If _DependingControl_In_Action Then + MyValidationLogger.Debug($"_dependingControl_in_action = True ==> Skip row!") + Continue For ' NEU: Continue statt Exit Sub – restliche Rows weiterverarbeiten + End If + + Dim oENABLE_GUID As Integer = CInt(oRowEnablingControl.Item("GUID")) Dim oENABLE_CtrlName = oRowEnablingControl.Item("NAME") MyValidationLogger.Debug($"Control {oENABLE_CtrlName} is depending on Control: {pControlName}..") - If _DependingControl_In_Action = True Then - MyValidationLogger.Debug($"..but _dependingControl_in_action = True ==> Exit Sub!") - Exit Sub + + Dim oConnectionId As Integer = oRowEnablingControl.ItemEx("CONNECTION_ID", 0) + Dim oSqlCommand As String = oRowEnablingControl.ItemEx("SQL_ENABLE", String.Empty) + + If oConnectionId = 0 OrElse String.IsNullOrEmpty(oSqlCommand) Then + MyValidationLogger.Debug($"Error: Check CoNN ID and SQL on NULL VALUES!") + Continue For End If - If Not IsDBNull(oRowEnablingControl.Item("CONNECTION_ID")) And Not IsDBNull(oRowEnablingControl.Item("SQL_ENABLE")) Then - Dim oSqlCommand = IIf(IsDBNull(oRowEnablingControl.Item("SQL_ENABLE")), "", oRowEnablingControl.Item("SQL_ENABLE")) - oSqlCommand = clsPatterns.ReplaceAllValues(oSqlCommand, PanelValidatorControl, True) - MyValidationLogger.Debug($"_DependingControl_In_Action: oENABLE_CtrlName {oENABLE_CtrlName} ...") - _DependingControl_In_Action = True - Dim oConnectionId As Integer = oRowEnablingControl.Item("CONNECTION_ID") + oSqlCommand = clsPatterns.ReplaceAllValues(oSqlCommand, PanelValidatorControl, True) + MyValidationLogger.Debug($"_DependingControl_In_Action: oENABLE_CtrlName {oENABLE_CtrlName} ...") + _DependingControl_In_Action = True + Try Dim oENABLERESULT As Boolean = False Dim oResult = GetCachedScalar(oSqlCommand, oConnectionId) If oResult IsNot Nothing AndAlso Not IsDBNull(oResult) Then oENABLERESULT = CBool(oResult) End If - Try - Dim oFound As Boolean = False - - For Each oControl As Control In PanelValidatorControl.Controls - If DirectCast(oControl.Tag, ClassControlCreator.ControlMetadata).Guid = oENABLE_GUID Then - oFound = True - MyValidationLogger.Debug($"Got the depending control ID:{oENABLE_GUID}..Setting enabled/Disabled...") - oControl.Enabled = oENABLERESULT - _DependingControl_In_Action = False - Exit For - End If + ' ========== OPTIMIERUNG: Dictionary-Lookup statt Panel-Loop ========== + Dim oControl As Control = Nothing + If _CachedControlsByGuid.TryGetValue(oENABLE_GUID, oControl) Then + MyValidationLogger.Debug($"Got the depending control ID:{oENABLE_GUID}..Setting enabled/Disabled...") + oControl.Enabled = oENABLERESULT + Else + MyValidationLogger.Debug($"Could not find the enabling Control with ID {oENABLE_GUID} on panel!!!") + End If + ' ========== ENDE OPTIMIERUNG ========== - Next - _DependingControl_In_Action = False - If oFound = False Then - MyValidationLogger.Debug($"Could not find the enabling Control with ID {oENABLE_GUID} on panel!!!") - End If - Catch ex As Exception - MyValidationLogger.Warn($"Error while setting enabling control-value for [{oENABLE_CtrlName}]: " & ex.Message) - _DependingControl_In_Action = False - End Try - Else - MyValidationLogger.Debug($"Error: Check CoNN ID and SQL on NULL VALUES!") - End If + Catch ex As Exception + MyValidationLogger.Warn($"Error while setting enabling control-value for [{oENABLE_CtrlName}]: " & ex.Message) + Finally + _DependingControl_In_Action = False + End Try Next Catch ex As Exception MyValidationLogger.Error(ex) End Try End Sub - 'Private Sub Controls2beDisabled() - ' Try - ' Dim oFilteredDatatable As DataTable = DT_CONTROLS.Clone() - ' Dim oExpression = $"LEN(SQL_ENABLE) > 0" - ' DT_CONTROLS.Select(oExpression).CopyToDataTable(oFilteredDatatable, LoadOption.PreserveChanges) - ' If oFilteredDatatable.Rows.Count > 0 Then - ' Logger.Debug($"We got {oFilteredDatatable.Rows.Count} controls which need to be disabled!!") - ' End If - ' For Each oRowEnablingControl As DataRow In oFilteredDatatable.Rows - ' Dim oENABLE_GUID = oRowEnablingControl.Item("GUID") - ' Dim oENABLE_CtrlName = oRowEnablingControl.Item("NAME") - ' For Each oControl As Control In PanelValidatorControl.Controls - ' If oENABLE_GUID = DirectCast(oControl.Tag, ClassControlCreator.ControlMetadata).Guid Then - ' oControl.Enabled = False - ' Exit For - ' End If - ' Next - ' Next - ' Catch ex As Exception - ' Logger.Error(ex) - ' End Try - 'End Sub Private Sub Controls2B_EnDisabled() If LOG_PERF Then PerformanceLogger.Info("Controls2B_EnDisabled") @@ -3816,825 +4068,871 @@ Public Class frmValidator ' VORHER: Verschachtelte Loops für Control-Suche → O(n²) ' NACHHER: Dictionary-Lookup → O(1) If _CachedControlsByGuid Is Nothing Then - _CachedControlsByGuid = New Dictionary(Of Integer, Control)() - For Each ctrl As Control In PanelValidatorControl.Controls - Try - Dim meta = DirectCast(ctrl.Tag, ClassControlCreator.ControlMetadata) - _CachedControlsByGuid(meta.Guid) = ctrl - Catch - Continue For - End Try - Next + _CachedControlsByGuid = New Dictionary(Of Integer, Control)() + For Each ctrl As Control In PanelValidatorControl.Controls + Try + Dim meta = DirectCast(ctrl.Tag, ClassControlCreator.ControlMetadata) + _CachedControlsByGuid(meta.Guid) = ctrl + Catch + Continue For + End Try + Next - If LOG_HOTSPOTS Then - MyValidationLogger.Info($"[PERF FillIndexValues] Nach _CachedControlsByGuid-Erstellung: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") - perfLastCheck = DateTime.Now - End If + If LOG_HOTSPOTS Then + MyValidationLogger.Info($"[PERF FillIndexValues] Nach _CachedControlsByGuid-Erstellung: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") + perfLastCheck = DateTime.Now End If - ' ========== ENDE OPTIMIERUNG 2 ========== - - ' ========== OPTIMIERUNG 3: UI-Updates pausieren (kritisch für Performance!) ========== - ' VORHER: Jede Zuweisung triggerte Repaint → tausende UI-Updates - ' NACHHER: Alle Updates gebündelt → nur ein Repaint am Ende - PanelValidatorControl.SuspendLayout() - Try - ' ========== ENDE OPTIMIERUNG 3 ========== - - If DTVWCONTROL_INDEX.Rows.Count > 0 Then - Dim oCount As Integer = 0 - For Each oControl As Control In Me.PanelValidatorControl.Controls - Dim oValueFromSource - Dim oFormattedValue As String = "" - - ' ========== OPTIMIERUNG 4: LINQ statt Loop für Control-Row-Suche ========== - ' VORHER: Implizite Loop über DTVWCONTROL_INDEX - ' NACHHER: Optimierter LINQ-Query mit SingleOrDefault - Dim oControlId = DirectCast(oControl.Tag, ClassControlCreator.ControlMetadata).Guid - Dim oControlRow = (From form In DTVWCONTROL_INDEX.AsEnumerable() - Where form.Item("GUID") = oControlId).SingleOrDefault() - - If oControlRow Is Nothing Then Continue For - ' ========== ENDE OPTIMIERUNG 4 ========== - - Dim oTyp As String = oControlRow.Item("CTRL_TYPE") - Dim oIDBTyp As String - If IDB_ACTIVE Then - oIDBTyp = oControlRow.Item("IDB_TYP") - End If + End If - Dim oSourceIndexName As String = oControlRow.Item("INDEX_NAME") - Dim oDefaultValue As String = ObjectEx.NotNull(oControlRow.Item("DEFAULT_VALUE"), String.Empty) - oIndexName = oSourceIndexName - oControName = oControl.Name - Dim oLoadIndex As Boolean = oControlRow.Item("LOAD_IDX_VALUE") - If oIndexName = "@@DISPLAY_ONLY" Then - oLoadIndex = False - End If - MyValidationLogger.Debug("INDEX: " & oSourceIndexName & " - CONTROLNAME: " & oControl.Name & " - LOAD IDXVALUES: " & oLoadIndex.ToString) + ' ========== ENDE OPTIMIERUNG 2 ========== - Select Case True - Case oControl.GetType = GetType(DevExpress.XtraEditors.TextEdit) Or oControl.GetType = GetType(MemoEdit) - If LOG_PERF Then PerformanceLogger.Info("FillIndexValues/TextEdit") + ' ========== OPTIMIERUNG 3: UI-Updates pausieren (kritisch für Performance!) ========== + ' VORHER: Jede Zuweisung triggerte Repaint → tausende UI-Updates + ' NACHHER: Alle Updates gebündelt → nur ein Repaint am Ende + PanelValidatorControl.SuspendLayout() + _suppressLookupEvents = True ' ← NEU: Events während FillIndexValues unterdrücken + Try + ' ========== ENDE OPTIMIERUNG 3 ========== - Try - oControlType = "Textbox" - Dim oTextBox As DevExpress.XtraEditors.TextEdit = oControl - Dim oMeta As ClassControlCreator.ControlMetadata = oTextBox.Tag + If DTVWCONTROL_INDEX.Rows.Count > 0 Then + Dim oCount As Integer = 0 + For Each oControl As Control In Me.PanelValidatorControl.Controls + Dim oValueFromSource + Dim oFormattedValue As String = "" + + ' ========== OPTIMIERUNG 4: LINQ statt Loop für Control-Row-Suche ========== + ' VORHER: Implizite Loop über DTVWCONTROL_INDEX + ' NACHHER: Optimierter LINQ-Query mit SingleOrDefault + Dim oControlId = DirectCast(oControl.Tag, ClassControlCreator.ControlMetadata).Guid + Dim oControlRow = (From form In DTVWCONTROL_INDEX.AsEnumerable() + Where form.Item("GUID") = oControlId).SingleOrDefault() + + If oControlRow Is Nothing Then Continue For + ' ========== ENDE OPTIMIERUNG 4 ========== + + Dim oTyp As String = oControlRow.Item("CTRL_TYPE") + Dim oIDBTyp As String + If IDB_ACTIVE Then + oIDBTyp = oControlRow.Item("IDB_TYP") + End If - If oSourceIndexName = "" Then - MsgBox("Attention wrong configuration:" & vbNewLine & "for control " & oControl.Name & " no INDEX configured!" & vbNewLine & "Bitte prüfen Sie den Formulardesigner!", MsgBoxStyle.Critical) - Exit For - End If - If oSourceIndexName Is Nothing = False Then - If oLoadIndex = False Then - MyValidationLogger.Debug($" oControl {oControl.Name}: Indexwert soll nicht geladen werden.") - If Not {"@@DISPLAY_ONLY", "DD PM-ONLY FOR DISPLAY"}.Contains(oSourceIndexName) Then - oTextBox.EditValue = oDefaultValue - End If - Exit Select - End If + Dim oSourceIndexName As String = oControlRow.Item("INDEX_NAME") + Dim oDefaultValue As String = ObjectEx.NotNull(oControlRow.Item("DEFAULT_VALUE"), String.Empty) + oIndexName = oSourceIndexName + oControName = oControl.Name + Dim oLoadIndex As Boolean = oControlRow.Item("LOAD_IDX_VALUE") + If oIndexName = "@@DISPLAY_ONLY" Then + oLoadIndex = False + End If + MyValidationLogger.Debug("INDEX: " & oSourceIndexName & " - CONTROLNAME: " & oControl.Name & " - LOAD IDXVALUES: " & oLoadIndex.ToString) - If oSourceIndexName.StartsWith("[%VKT") And PROFIL_VEKTORINDEX <> "" Then - oValueFromSource = ReturnVektor_IndexValue(oSourceIndexName) - Else - oValueFromSource = GetVariableValuefromSource(oSourceIndexName, oIDBTyp, oIDBOverride) + Select Case True + Case oControl.GetType = GetType(DevExpress.XtraEditors.TextEdit) Or oControl.GetType = GetType(MemoEdit) + If LOG_PERF Then PerformanceLogger.Info("FillIndexValues/TextEdit") - If oValueFromSource Is Nothing Then - oValueFromSource = "" - Else - If oValueFromSource.ToString = "System.Object[]" Then - MyValidationLogger.Debug("TextBox with VektorField: " & oSourceIndexName) - Try - MyValidationLogger.Debug($"Length of Vektorarray: {oValueFromSource.length}") - Catch ex As Exception - MyValidationLogger.Info($"Error in gettin the lenth of vektorfield {oSourceIndexName} - {ex.Message}") - End Try - If oValueFromSource.length = 1 Then - oValueFromSource = oValueFromSource(0) - Else - MyValidationLogger.Info(" >> Vectorfield " & oSourceIndexName & "' contains more then one value - First value will be used") - oValueFromSource = oValueFromSource(0) - End If - MyValidationLogger.Debug($"wertWD has been saved...") - End If - End If - End If + Try + oControlType = "Textbox" + Dim oTextBox As DevExpress.XtraEditors.TextEdit = oControl + Dim oMeta As ClassControlCreator.ControlMetadata = oTextBox.Tag - MyValidationLogger.Debug("Value from Source: [{0}]", oValueFromSource) + If oSourceIndexName = "" Then + MsgBox("Attention wrong configuration:" & vbNewLine & "for control " & oControl.Name & " no INDEX configured!" & vbNewLine & "Bitte prüfen Sie den Formulardesigner!", MsgBoxStyle.Critical) + Exit For + End If + If oSourceIndexName Is Nothing = False Then + If oLoadIndex = False Then + MyValidationLogger.Debug($" oControl {oControl.Name}: Indexwert soll nicht geladen werden.") + If Not {"@@DISPLAY_ONLY", "DD PM-ONLY FOR DISPLAY"}.Contains(oSourceIndexName) Then + oTextBox.EditValue = oDefaultValue + End If + Exit Select + End If - Try - Dim oFormatString As String = oControlRow.ItemEx("CTRL_FORMAT_STRING", "") - oTextBox.EditValue = ObjectEx.NotNull(oValueFromSource, oDefaultValue) + If oSourceIndexName.StartsWith("[%VKT") And PROFIL_VEKTORINDEX <> "" Then + oValueFromSource = ReturnVektor_IndexValue(oSourceIndexName) + Else + oValueFromSource = GetVariableValuefromSource(oSourceIndexName, oIDBTyp, oIDBOverride) - If oControl.GetType = GetType(DevExpress.XtraEditors.TextEdit) And oFormatString = "CURRENCY" Then - ApplyCurrencyMask(oTextBox) + If oValueFromSource Is Nothing Then + oValueFromSource = "" + Else + If oValueFromSource.ToString = "System.Object[]" Then + MyValidationLogger.Debug("TextBox with VektorField: " & oSourceIndexName) + Try + MyValidationLogger.Debug($"Length of Vektorarray: {oValueFromSource.length}") + Catch ex As Exception + MyValidationLogger.Info($"Error in gettin the lenth of vektorfield {oSourceIndexName} - {ex.Message}") + End Try + If oValueFromSource.length = 1 Then + oValueFromSource = oValueFromSource(0) + Else + MyValidationLogger.Info(" >> Vectorfield " & oSourceIndexName & "' contains more then one value - First value will be used") + oValueFromSource = oValueFromSource(0) + End If + MyValidationLogger.Debug($"wertWD has been saved...") End If + End If + End If - ' BackColor-Logik - Try - Dim oBackColor As String = oControlRow.Item("CTRL_BACKCOLOR_IF") - If oBackColor <> String.Empty Then - Dim oSPlit = Split(oBackColor, ";") - If oSPlit.Length = 3 Then - Dim oValueConverted - If IsNumeric(oValueFromSource) Then - oValueConverted = oValueFromSource.ToString.Replace(",", ".") - Else - oValueConverted = oValueFromSource - End If - Dim oExpression = $"{oValueConverted} {oSPlit(0)}" + MyValidationLogger.Debug("Value from Source: [{0}]", oValueFromSource) - Dim oSQl = $"SELECT CASE WHEN {oExpression} THEN CONVERT(BIT,1) ELSE CONVERT(BIT,0) END " - Dim oColorName = IIf(DatabaseECM.GetScalarValue(oSQl), oSPlit(1), oSPlit(2)) + Try + Dim oFormatString As String = oControlRow.ItemEx("CTRL_FORMAT_STRING", "") + oTextBox.EditValue = ObjectEx.NotNull(oValueFromSource, oDefaultValue) + + If oControl.GetType = GetType(DevExpress.XtraEditors.TextEdit) And oFormatString = "CURRENCY" Then + ApplyCurrencyMask(oTextBox) + End If - oControl.BackColor = Color.FromName(oColorName) - oMeta.BackColor = oControl.BackColor - oControl.ForeColor = GraphicsEx.GetContrastedColor(oControl.BackColor) + ' BackColor-Logik + Try + Dim oBackColor As String = oControlRow.Item("CTRL_BACKCOLOR_IF") + If oBackColor <> String.Empty Then + Dim oSPlit = Split(oBackColor, ";") + If oSPlit.Length = 3 Then + Dim oValueConverted + If IsNumeric(oValueFromSource) Then + oValueConverted = oValueFromSource.ToString.Replace(",", ".") + Else + oValueConverted = oValueFromSource End If - End If - Catch ex As Exception - MyValidationLogger.Warn($"Unexpected error in Set Backcolor [{oControl.Name}]: {ex.Message}") - MyValidationLogger.Error(ex) - End Try + Dim oExpression = $"{oValueConverted} {oSPlit(0)}" - ' ========== OPTIMIERUNG 5: GridTables erst NACH allen TextBox-Updates ========== - ' NACHHER wird dies EINMAL am Ende aufgerufen (siehe unten) - ' ========== ENDE OPTIMIERUNG 5 ========== + Dim oSQl = $"SELECT CASE WHEN {oExpression} THEN CONVERT(BIT,1) ELSE CONVERT(BIT,0) END " + Dim oColorName = IIf(DatabaseECM.GetScalarValue(oSQl), oSPlit(1), oSPlit(2)) + oControl.BackColor = Color.FromName(oColorName) + oMeta.BackColor = oControl.BackColor + oControl.ForeColor = GraphicsEx.GetContrastedColor(oControl.BackColor) + End If + End If Catch ex As Exception - MyValidationLogger.Info("Error While converting defaultValue [" & oDefaultValue & "]: " & ex.Message) - oTextBox.EditValue = "" + MyValidationLogger.Warn($"Unexpected error in Set Backcolor [{oControl.Name}]: {ex.Message}") + MyValidationLogger.Error(ex) End Try - End If - Catch ex As Exception - MyValidationLogger.Error(ex) - errormessage = $"Unvorhergesehener Fehler bei FillIndexValues TextBox [{oControl.Name}]:" & vbNewLine & ex.Message & vbNewLine & "Check Logfile" - My.Settings.Save() - frmError.ShowDialog() - MyValidationLogger.Info("Unexpected error in FillIndexValuesTextBox: " & ex.Message, True) - MyValidationLogger.Info(">> Controltype: " & oControlType) - MyValidationLogger.Info(">> Indexname windream: " & oIndexName) - Exit Sub - End Try - Case oControl.GetType = GetType(Windows.Forms.ComboBox) - If LOG_PERF Then PerformanceLogger.Info("FillIndexValues/ComboBox") + ' ========== OPTIMIERUNG 5: GridTables erst NACH allen TextBox-Updates ========== + ' NACHHER wird dies EINMAL am Ende aufgerufen (siehe unten) + ' ========== ENDE OPTIMIERUNG 5 ========== - oControlType = "ComboBox" - Dim oMyCombobox As Windows.Forms.ComboBox = oControl - Try - If oSourceIndexName = "" Then - MsgBox("Attention wrong configuration:" & vbNewLine & "for control " & oControl.Name & " no INDEX configured!" & vbNewLine & "Bitte prüfen Sie den Formulardesigner!", MsgBoxStyle.Critical) - Exit For - End If - If oSourceIndexName Is Nothing = False Then - If oLoadIndex = False Then - MyValidationLogger.Debug($" oMyComboBox {oMyCombobox.Name}: Indexwert soll nicht geladen werden.") - If Not {"@@DISPLAY_ONLY", "DD PM-ONLY FOR DISPLAY"}.Contains(oSourceIndexName) Then - If oDefaultValue = String.Empty Then - oMyCombobox.SelectedIndex = -1 - Else - oMyCombobox.Text = oDefaultValue - End If - End If - Exit Select - End If + Catch ex As Exception + MyValidationLogger.Info("Error While converting defaultValue [" & oDefaultValue & "]: " & ex.Message) + oTextBox.EditValue = "" + End Try + End If + Catch ex As Exception + MyValidationLogger.Error(ex) + errormessage = $"Unvorhergesehener Fehler bei FillIndexValues TextBox [{oControl.Name}]:" & vbNewLine & ex.Message & vbNewLine & "Check Logfile" + My.Settings.Save() + frmError.ShowDialog() + MyValidationLogger.Info("Unexpected error in FillIndexValuesTextBox: " & ex.Message, True) + MyValidationLogger.Info(">> Controltype: " & oControlType) + MyValidationLogger.Info(">> Indexname windream: " & oIndexName) + Exit Sub + End Try - If oSourceIndexName.StartsWith("[%VKT") And PROFIL_VEKTORINDEX <> "" Then - oValueFromSource = ReturnVektor_IndexValue(oSourceIndexName) - Else - oValueFromSource = GetVariableValuefromSource(oSourceIndexName, oIDBTyp, oIDBOverride) - End If + Case oControl.GetType = GetType(Windows.Forms.ComboBox) + If LOG_PERF Then PerformanceLogger.Info("FillIndexValues/ComboBox") - If oValueFromSource Is Nothing Then - MyValidationLogger.Debug($"oMyComboBox {oMyCombobox.Name} - Indexvalue from index {oSourceIndexName}: Nothing") + oControlType = "ComboBox" + Dim oMyCombobox As Windows.Forms.ComboBox = oControl + Try + If oSourceIndexName = "" Then + MsgBox("Attention wrong configuration:" & vbNewLine & "for control " & oControl.Name & " no INDEX configured!" & vbNewLine & "Bitte prüfen Sie den Formulardesigner!", MsgBoxStyle.Critical) + Exit For + End If + If oSourceIndexName Is Nothing = False Then + If oLoadIndex = False Then + MyValidationLogger.Debug($" oMyComboBox {oMyCombobox.Name}: Indexwert soll nicht geladen werden.") + If Not {"@@DISPLAY_ONLY", "DD PM-ONLY FOR DISPLAY"}.Contains(oSourceIndexName) Then If oDefaultValue = String.Empty Then - MyValidationLogger.Debug($"oMyComboBox {oMyCombobox.Name}-defaultValue wurde nicht gefunden") oMyCombobox.SelectedIndex = -1 Else - MyValidationLogger.Debug($"oMyComboBox {oMyCombobox.Name}-defaultValue wird geladen") oMyCombobox.Text = oDefaultValue End If - Else - If oValueFromSource.ToString = "System.Object[]" Then - MyValidationLogger.Debug($"oMyComboBox {oMyCombobox.Name} - Combobox with VektorField: " & oSourceIndexName) - Try - MyValidationLogger.Debug($"Length of Vektorarray: {oValueFromSource.length}") - Catch ex As Exception - MyValidationLogger.Info($"Error in gettin the length of vektorfield {oSourceIndexName} - {ex.Message}") - End Try - If oValueFromSource.length = 1 Then - oValueFromSource = oValueFromSource(0) - Else - MyValidationLogger.Info(" >> Vectorfield " & oSourceIndexName & "' contains more then one value - First value will be used") - oValueFromSource = oValueFromSource(0) - End If - MyValidationLogger.Debug($"wertWD has been saved...") - End If - MyValidationLogger.Debug($"Indexwert from Index {oSourceIndexName}: {oValueFromSource}") - MyValidationLogger.Debug($"Items in Combobox: {oMyCombobox.Items.Count}") + End If + Exit Select + End If + + If oSourceIndexName.StartsWith("[%VKT") And PROFIL_VEKTORINDEX <> "" Then + oValueFromSource = ReturnVektor_IndexValue(oSourceIndexName) + Else + oValueFromSource = GetVariableValuefromSource(oSourceIndexName, oIDBTyp, oIDBOverride) + End If - If oMyCombobox.Items.Count = 0 Then - oMyCombobox.Text = oValueFromSource + If oValueFromSource Is Nothing Then + MyValidationLogger.Debug($"oMyComboBox {oMyCombobox.Name} - Indexvalue from index {oSourceIndexName}: Nothing") + If oDefaultValue = String.Empty Then + MyValidationLogger.Debug($"oMyComboBox {oMyCombobox.Name}-defaultValue wurde nicht gefunden") + oMyCombobox.SelectedIndex = -1 + Else + MyValidationLogger.Debug($"oMyComboBox {oMyCombobox.Name}-defaultValue wird geladen") + oMyCombobox.Text = oDefaultValue + End If + Else + If oValueFromSource.ToString = "System.Object[]" Then + MyValidationLogger.Debug($"oMyComboBox {oMyCombobox.Name} - Combobox with VektorField: " & oSourceIndexName) + Try + MyValidationLogger.Debug($"Length of Vektorarray: {oValueFromSource.length}") + Catch ex As Exception + MyValidationLogger.Info($"Error in gettin the length of vektorfield {oSourceIndexName} - {ex.Message}") + End Try + If oValueFromSource.length = 1 Then + oValueFromSource = oValueFromSource(0) Else - MyValidationLogger.Debug($"Index Wert [{oValueFromSource}] wurde ausgewählt") - oMyCombobox.SelectedIndex = oMyCombobox.FindStringExact(oValueFromSource) - MyValidationLogger.Debug($"oMyComboBox {oMyCombobox.Name} .SelectedIndex: {oMyCombobox.SelectedIndex}") + MyValidationLogger.Info(" >> Vectorfield " & oSourceIndexName & "' contains more then one value - First value will be used") + oValueFromSource = oValueFromSource(0) End If + MyValidationLogger.Debug($"wertWD has been saved...") + End If + MyValidationLogger.Debug($"Indexwert from Index {oSourceIndexName}: {oValueFromSource}") + MyValidationLogger.Debug($"Items in Combobox: {oMyCombobox.Items.Count}") + + If oMyCombobox.Items.Count = 0 Then + oMyCombobox.Text = oValueFromSource + Else + MyValidationLogger.Debug($"Index Wert [{oValueFromSource}] wurde ausgewählt") + oMyCombobox.SelectedIndex = oMyCombobox.FindStringExact(oValueFromSource) + MyValidationLogger.Debug($"oMyComboBox {oMyCombobox.Name} .SelectedIndex: {oMyCombobox.SelectedIndex}") End If End If - MyValidationLogger.Debug("") - Catch ex As Exception - MyValidationLogger.Error(ex) - MyValidationLogger.Info(">> Unexpected error in FillIndexValues(Combobox: " & oMyCombobox.Name & "): " & ex.Message, True) - MyValidationLogger.Info(">> Controltype: " & oControlType) - MyValidationLogger.Info(">> Indexname windream: " & oIndexName) - errormessage = "Unexpected error in FillIndexValues(Combobox: " & oMyCombobox.Name & "): " & vbNewLine & ex.Message & vbNewLine & "Check Logfile" - My.Settings.Save() - frmError.ShowDialog() - End Try + End If + MyValidationLogger.Debug("") + Catch ex As Exception + MyValidationLogger.Error(ex) + MyValidationLogger.Info(">> Unexpected error in FillIndexValues(Combobox: " & oMyCombobox.Name & "): " & ex.Message, True) + MyValidationLogger.Info(">> Controltype: " & oControlType) + MyValidationLogger.Info(">> Indexname windream: " & oIndexName) + errormessage = "Unexpected error in FillIndexValues(Combobox: " & oMyCombobox.Name & "): " & vbNewLine & ex.Message & vbNewLine & "Check Logfile" + My.Settings.Save() + frmError.ShowDialog() + End Try - Case oControl.GetType = GetType(GridControl) - If LOG_PERF Then PerformanceLogger.Info("FillIndexValues/GridControl") + Case oControl.GetType = GetType(GridControl) + If LOG_PERF Then PerformanceLogger.Info("FillIndexValues/GridControl") - oControlType = "DevExpress.XtraGrid.GridControl" - Dim oMyGridControl As GridControl = oControl + oControlType = "DevExpress.XtraGrid.GridControl" + Dim oMyGridControl As GridControl = oControl - ' ========== OPTIMIERUNG 6: Dictionary-Lookup statt Select() ========== - ' VORHER: DT_COLUMNS_GRID.Select($"CONTROL_ID = {oControlId}") → O(n) pro Grid - ' NACHHER: Dictionary.TryGetValue() → O(1) - Dim oDTColumnsPerDevExGrid As DataTable = Nothing - If columnsByControl IsNot Nothing AndAlso columnsByControl.TryGetValue(oControlId, oDTColumnsPerDevExGrid) Then - MyValidationLogger.Debug($"Grid [{oControl.Name}]: {oDTColumnsPerDevExGrid.Rows.Count} Spalten aus Cache geladen") - Else - oDTColumnsPerDevExGrid = DT_COLUMNS_GRID.Clone() - MyValidationLogger.Warn($"Grid [{oControl.Name}]: Keine Spalten-Definition gefunden!") - End If - ' ========== ENDE OPTIMIERUNG 6 ========== + ' ========== OPTIMIERUNG 6: Dictionary-Lookup statt Select() ========== + ' VORHER: DT_COLUMNS_GRID.Select($"CONTROL_ID = {oControlId}") → O(n) pro Grid + ' NACHHER: Dictionary.TryGetValue() → O(1) + Dim oDTColumnsPerDevExGrid As DataTable = Nothing + If columnsByControl IsNot Nothing AndAlso columnsByControl.TryGetValue(oControlId, oDTColumnsPerDevExGrid) Then + MyValidationLogger.Debug($"Grid [{oControl.Name}]: {oDTColumnsPerDevExGrid.Rows.Count} Spalten aus Cache geladen") + Else + oDTColumnsPerDevExGrid = DT_COLUMNS_GRID.Clone() + MyValidationLogger.Warn($"Grid [{oControl.Name}]: Keine Spalten-Definition gefunden!") + End If + ' ========== ENDE OPTIMIERUNG 6 ========== - Try - If oSourceIndexName = "" Then - MsgBox("Attention wrong configuration:" & vbNewLine & "for control " & oControl.Name & " no INDEX configured!" & vbNewLine & "Bitte prüfen Sie den Formulardesigner!", MsgBoxStyle.Critical, ADDITIONAL_TITLE) - Exit For + Try + If oSourceIndexName = "" Then + MsgBox("Attention wrong configuration:" & vbNewLine & "for control " & oControl.Name & " no INDEX configured!" & vbNewLine & "Bitte prüfen Sie den Formulardesigner!", MsgBoxStyle.Critical, ADDITIONAL_TITLE) + Exit For + End If + If oSourceIndexName Is Nothing = False Then + If oLoadIndex = False Then + MyValidationLogger.Debug($" oControl {oControl.Name}: Indexwert soll nicht geladen werden.") + Exit Select End If - If oSourceIndexName Is Nothing = False Then - If oLoadIndex = False Then - MyValidationLogger.Debug($" oControl {oControl.Name}: Indexwert soll nicht geladen werden.") - Exit Select - End If - MyValidationLogger.Debug($"getting Value for Attribute [{oSourceIndexName}] - oIDBTyp [{oIDBTyp}] - oIDBOverride [{oIDBOverride}]...") - oValueFromSource = GetVariableValuefromSource(oSourceIndexName, oIDBTyp, oIDBOverride) + MyValidationLogger.Debug($"getting Value for Attribute [{oSourceIndexName}] - oIDBTyp [{oIDBTyp}] - oIDBOverride [{oIDBOverride}]...") + oValueFromSource = GetVariableValuefromSource(oSourceIndexName, oIDBTyp, oIDBOverride) + + If oValueFromSource Is Nothing = False Then + Dim oValueType = oValueFromSource.GetType.ToString + MyValidationLogger.Debug($"oValueType is [{oValueType}]!") + + If oValueType.Contains("System.Object") Or oValueType = "System.Data.DataTable" Or oValueType = "System.String" Then + Select Case oTyp + Case "TABLE" + Dim oColValuesfromSource As String() + MyValidationLogger.Debug($"DevExpressGrid: {oDTColumnsPerDevExGrid.Rows.Count} Columns configured for control {oControlId}.") - If oValueFromSource Is Nothing = False Then - Dim oValueType = oValueFromSource.GetType.ToString - MyValidationLogger.Debug($"oValueType is [{oValueType}]!") - - If oValueType.Contains("System.Object") Or oValueType = "System.Data.DataTable" Or oValueType = "System.String" Then - Select Case oTyp - Case "TABLE" - Dim oColValuesfromSource As String() - MyValidationLogger.Debug($"DevExpressGrid: {oDTColumnsPerDevExGrid.Rows.Count} Columns configured for control {oControlId}.") - - If oDTColumnsPerDevExGrid.Rows.Count >= 1 Then - Dim oDataSource As DataTable = oMyGridControl.DataSource - oDataSource.Rows.Clear() - If IDB_ACTIVE = False Then - MyValidationLogger.Debug("ValueFromSource contains {0} items", oValueFromSource) - - For Each Zeile As Object In oValueFromSource - MyValidationLogger.Debug($"vektorrow Value {Zeile.ToString}...") - oColValuesfromSource = Split(Zeile, PMDelimiter) - Dim oNewRow = oDataSource.NewRow() - MyValidationLogger.Debug("Creating new row..") - - For index = 0 To oDTColumnsPerDevExGrid.Rows.Count - 1 - Dim rawValue As String = If(index < oColValuesfromSource.Length, oColValuesfromSource(index), String.Empty) - Dim targetColumn As DataColumn = oDataSource.Columns(index) - Dim colName As String = targetColumn.ColumnName - Dim colType As String = targetColumn.DataType.FullName - - MyValidationLogger.Debug("Grid row assign: RowIdx={0}, ColIdx={1}, ColName={2}, ColType={3}, RawValue=[{4}], IsEmpty={5}", + If oDTColumnsPerDevExGrid.Rows.Count >= 1 Then + Dim oDataSource As DataTable = oMyGridControl.DataSource + oDataSource.Rows.Clear() + If IDB_ACTIVE = False Then + MyValidationLogger.Debug("ValueFromSource contains {0} items", oValueFromSource) + + For Each Zeile As Object In oValueFromSource + MyValidationLogger.Debug($"vektorrow Value {Zeile.ToString}...") + oColValuesfromSource = Split(Zeile, PMDelimiter) + Dim oNewRow = oDataSource.NewRow() + MyValidationLogger.Debug("Creating new row..") + + For index = 0 To oDTColumnsPerDevExGrid.Rows.Count - 1 + Dim rawValue As String = If(index < oColValuesfromSource.Length, oColValuesfromSource(index), String.Empty) + Dim targetColumn As DataColumn = oDataSource.Columns(index) + Dim colName As String = targetColumn.ColumnName + Dim colType As String = targetColumn.DataType.FullName + + MyValidationLogger.Debug("Grid row assign: RowIdx={0}, ColIdx={1}, ColName={2}, ColType={3}, RawValue=[{4}], IsEmpty={5}", oDataSource.Rows.Count, index, colName, colType, rawValue, String.IsNullOrWhiteSpace(rawValue)) - Try - If oColValuesfromSource.Length > index Then - oNewRow.Item(index) = oColValuesfromSource(index) + Try + If oColValuesfromSource.Length > index Then + oNewRow.Item(index) = oColValuesfromSource(index) + Else + If colType = "System.Double" Or colType = "System.Int32" Or colType = "System.Int64" Then + oNewRow.Item(index) = 0 Else - If colType = "System.Double" Or colType = "System.Int32" Or colType = "System.Int64" Then - oNewRow.Item(index) = 0 - Else - oNewRow.Item(index) = String.Empty - End If + oNewRow.Item(index) = String.Empty End If - Catch ex As Exception - MyValidationLogger.Warn("⚠️ Grid row assign FAILED RowIdx = {0}, ColIdx={1}, ColName={2}, ColType={3}, RawValue=[{4}]", + End If + Catch ex As Exception + MyValidationLogger.Warn("⚠️ Grid row assign FAILED RowIdx = {0}, ColIdx={1}, ColName={2}, ColType={3}, RawValue=[{4}]", oDataSource.Rows.Count, index, colName, colType, rawValue) - MyValidationLogger.Error(ex) - Try - MyValidationLogger.Debug("Column.AllowDBNull={0}, Column.MaxLength={1}", targetColumn.AllowDBNull, targetColumn.MaxLength) - Catch - End Try - Throw + MyValidationLogger.Error(ex) + Try + MyValidationLogger.Debug("Column.AllowDBNull={0}, Column.MaxLength={1}", targetColumn.AllowDBNull, targetColumn.MaxLength) + Catch End Try - Next - MyValidationLogger.Debug("Adding row To grid..") - oDataSource.Rows.Add(oNewRow) + Throw + End Try Next - Else - ' IDB-Logik (bleibt gleich) - If oValueType = "System.String" Then - MyValidationLogger.Debug($"IDB Fill Grid [{oControl.Name}] With String") - MyValidationLogger.Debug($"oValueFromSource [{oValueFromSource}] - PMDelimiter[{PMDelimiter}]") - - oColValuesfromSource = Split(oValueFromSource.ToString, PMDelimiter) - If oColValuesfromSource.Length > 8 Then - MyValidationLogger.Warn("⚠️ Fill Grid Error - Max 8 columns can be configured!") + MyValidationLogger.Debug("Adding row To grid..") + oDataSource.Rows.Add(oNewRow) + Next + Else + ' IDB-Logik (bleibt gleich) + If oValueType = "System.String" Then + MyValidationLogger.Debug($"IDB Fill Grid [{oControl.Name}] With String") + MyValidationLogger.Debug($"oValueFromSource [{oValueFromSource}] - PMDelimiter[{PMDelimiter}]") + + oColValuesfromSource = Split(oValueFromSource.ToString, PMDelimiter) + If oColValuesfromSource.Length > 8 Then + MyValidationLogger.Warn("⚠️ Fill Grid Error - Max 8 columns can be configured!") + End If + + Dim oRowData As New List(Of Object) + MyValidationLogger.Debug(String.Format("Now creating the rows For DevexpressGrid ...")) + Dim oMSG = "" + Try + For index = 1 To oColValuesfromSource.Length + oMSG = "" + Dim oValue = oColValuesfromSource(index - 1) + oMSG = String.Format("...Index [{0}] - Value [{1}]", index, oValue) + MyValidationLogger.Debug(oMSG) + If oDTColumnsPerDevExGrid.Rows.Count > (index - 1) Then + Dim oColumnType = oDTColumnsPerDevExGrid.Rows.Item(index - 1).Item("TYPE_COLUMN") + Dim oConvertedValue = ClassFormat.GetConvertedValue(oValue, oColumnType) + oRowData.Add(oConvertedValue) + Else + MyValidationLogger.Warn(String.Format("Mehr Values als Spaten in oDTColumnsPerDevExGrid {0}", oControl.Name)) + End If + Next + Catch ex As Exception + MyValidationLogger.Warn(String.Format("Unexpected Error While working On IDB Fill GridControl {0}", oControl.Name)) + If Not oMSG = String.Empty Then + MyValidationLogger.Warn(String.Format("oMSG {0}", oMSG)) End If + MyValidationLogger.Error(ex) + End Try + + oDataSource.Rows.Add(oRowData.ToArray()) - Dim oRowData As New List(Of Object) - MyValidationLogger.Debug(String.Format("Now creating the rows For DevexpressGrid ...")) - Dim oMSG = "" + ElseIf oValueType = "System.Data.DataTable" Then + Dim oMyDatatable As DataTable = oValueFromSource + MyValidationLogger.Debug($"IDB Fill Grid [{oControl.Name}] With Datatable - Rows " & oMyDatatable.Rows.Count) + For Each oRow As DataRow In oMyDatatable.Rows Try + MyValidationLogger.Debug($"IDB ROW Vector {oRow.Item(0).ToString}...") + oColValuesfromSource = Split(oRow.Item(0).ToString, PMDelimiter) + + If oColValuesfromSource.Length > 8 Then + MyValidationLogger.Warn("⚠️ Fill Grid With DatatableSplit Error - Max 8 columns can be configured!") + End If + MyValidationLogger.Debug($"oColValuesfromSource splitted - Length ({oColValuesfromSource.Length.ToString})") + Dim oRowData As New List(Of Object) + For index = 1 To oColValuesfromSource.Length - oMSG = "" - Dim oValue = oColValuesfromSource(index - 1) - oMSG = String.Format("...Index [{0}] - Value [{1}]", index, oValue) - MyValidationLogger.Debug(oMSG) - If oDTColumnsPerDevExGrid.Rows.Count > (index - 1) Then + Try Dim oColumnType = oDTColumnsPerDevExGrid.Rows.Item(index - 1).Item("TYPE_COLUMN") - Dim oConvertedValue = ClassFormat.GetConvertedValue(oValue, oColumnType) + MyValidationLogger.Debug($"oColumnType Of DGView-Column ({oColumnType.ToString})...") + Dim oConvertedValue = ClassFormat.GetConvertedValue(oColValuesfromSource(index - 1), oColumnType) oRowData.Add(oConvertedValue) - Else - MyValidationLogger.Warn(String.Format("Mehr Values als Spaten in oDTColumnsPerDevExGrid {0}", oControl.Name)) - End If + Catch ex As Exception + MyValidationLogger.Warn($"Error While converting/adding Value To oRowData " & ex.Message) + End Try Next + oDataSource.Rows.Add(oRowData.ToArray()) Catch ex As Exception - MyValidationLogger.Warn(String.Format("Unexpected Error While working On IDB Fill GridControl {0}", oControl.Name)) - If Not oMSG = String.Empty Then - MyValidationLogger.Warn(String.Format("oMSG {0}", oMSG)) - End If - MyValidationLogger.Error(ex) + MyValidationLogger.Warn($"Error While adding datarow [{oRow.Item(0).ToString}] To Grid " & ex.Message) End Try - - oDataSource.Rows.Add(oRowData.ToArray()) - - ElseIf oValueType = "System.Data.DataTable" Then - Dim oMyDatatable As DataTable = oValueFromSource - MyValidationLogger.Debug($"IDB Fill Grid [{oControl.Name}] With Datatable - Rows " & oMyDatatable.Rows.Count) - For Each oRow As DataRow In oMyDatatable.Rows - Try - MyValidationLogger.Debug($"IDB ROW Vector {oRow.Item(0).ToString}...") - oColValuesfromSource = Split(oRow.Item(0).ToString, PMDelimiter) - - If oColValuesfromSource.Length > 8 Then - MyValidationLogger.Warn("⚠️ Fill Grid With DatatableSplit Error - Max 8 columns can be configured!") - End If - MyValidationLogger.Debug($"oColValuesfromSource splitted - Length ({oColValuesfromSource.Length.ToString})") - Dim oRowData As New List(Of Object) - - For index = 1 To oColValuesfromSource.Length - Try - Dim oColumnType = oDTColumnsPerDevExGrid.Rows.Item(index - 1).Item("TYPE_COLUMN") - MyValidationLogger.Debug($"oColumnType Of DGView-Column ({oColumnType.ToString})...") - Dim oConvertedValue = ClassFormat.GetConvertedValue(oColValuesfromSource(index - 1), oColumnType) - oRowData.Add(oConvertedValue) - Catch ex As Exception - MyValidationLogger.Warn($"Error While converting/adding Value To oRowData " & ex.Message) - End Try - Next - oDataSource.Rows.Add(oRowData.ToArray()) - Catch ex As Exception - MyValidationLogger.Warn($"Error While adding datarow [{oRow.Item(0).ToString}] To Grid " & ex.Message) - End Try - Next - End If + Next End If - Else - MyValidationLogger.Info($"DevExpressGrid There are no columns configured/listed For control {oControlId}.") End If + Else + MyValidationLogger.Info($"DevExpressGrid There are no columns configured/listed For control {oControlId}.") + End If - Case Else - Dim oDataSource As DataTable = oMyGridControl.DataSource - For Each obj As Object In oValueFromSource - If obj Is Nothing = False Then - oDataSource.Rows.Add(New String() {obj.ToString}) - End If - Next - End Select - Else - MyValidationLogger.Warn($"Could Not load Devexpress.Grid [{oControl.Name }] As omytype Is [{oValueType}]!") - End If + Case Else + Dim oDataSource As DataTable = oMyGridControl.DataSource + For Each obj As Object In oValueFromSource + If obj Is Nothing = False Then + oDataSource.Rows.Add(New String() {obj.ToString}) + End If + Next + End Select Else - If first = False Then - Dim oDataSource As DataTable = oMyGridControl.DataSource - If oDataSource.Rows.Count > 0 Then - oDataSource.Rows.Clear() - End If + MyValidationLogger.Warn($"Could Not load Devexpress.Grid [{oControl.Name }] As omytype Is [{oValueType}]!") + End If + Else + If first = False Then + Dim oDataSource As DataTable = oMyGridControl.DataSource + If oDataSource.Rows.Count > 0 Then + oDataSource.Rows.Clear() End If End If + End If - ' ========== OPTIMIERUNG 7: GridView-Spaltenbreiten mit Dictionary ========== - ' VORHER: Verschachtelte Loop über Columns × oDTColumnsPerDevExGrid → O(n × m) - ' NACHHER: Dictionary-Lookup → O(n + m) - Try - Dim oMyGridView As DevExpress.XtraGrid.Views.Grid.GridView = oMyGridControl.MainView - oMyGridView.OptionsView.ColumnAutoWidth = False + ' ========== OPTIMIERUNG 7: GridView-Spaltenbreiten mit Dictionary ========== + ' VORHER: Verschachtelte Loop über Columns × oDTColumnsPerDevExGrid → O(n × m) + ' NACHHER: Dictionary-Lookup → O(n + m) + Try + Dim oMyGridView As DevExpress.XtraGrid.Views.Grid.GridView = oMyGridControl.MainView + oMyGridView.OptionsView.ColumnAutoWidth = False - If oDTColumnsPerDevExGrid IsNot Nothing AndAlso oDTColumnsPerDevExGrid.Rows.Count > 0 Then - Dim columnsByName = oMyGridView.Columns.Cast(Of GridColumn)(). + If oDTColumnsPerDevExGrid IsNot Nothing AndAlso oDTColumnsPerDevExGrid.Rows.Count > 0 Then + Dim columnsByName = oMyGridView.Columns.Cast(Of GridColumn)(). ToDictionary(Function(c) c.FieldName, StringComparer.OrdinalIgnoreCase) - For Each oRow As DataRow In oDTColumnsPerDevExGrid.Rows - Dim columnName = oRow.Item("SPALTENNAME").ToString() - Dim column As GridColumn = Nothing + For Each oRow As DataRow In oDTColumnsPerDevExGrid.Rows + Dim columnName = oRow.Item("SPALTENNAME").ToString() + Dim column As GridColumn = Nothing - If columnsByName.TryGetValue(columnName, column) Then - column.Width = oRow.Item("SPALTENBREITE") - End If - Next - End If - Catch ex As Exception - MyValidationLogger.Error(ex) - End Try - ' ========== ENDE OPTIMIERUNG 7 ========== - End If - Catch ex As Exception - MyValidationLogger.Error(ex) - MyValidationLogger.Info(">> Unexpected Error In FillIndexValues(GridControl " & oMyGridControl.Name & ") " & ex.Message, True) - MyValidationLogger.Info(">> Controltype " & oControlType) - MyValidationLogger.Info(">> Attributname " & oIndexName) - errormessage = "Unexpected Error In FillIndexValues(Combobox " & oMyGridControl.Name & ") " & vbNewLine & ex.Message & vbNewLine & "Check Logfile" - My.Settings.Save() - frmError.ShowDialog() - End Try + If columnsByName.TryGetValue(columnName, column) Then + column.Width = oRow.Item("SPALTENBREITE") + End If + Next + End If + Catch ex As Exception + MyValidationLogger.Error(ex) + End Try + ' ========== ENDE OPTIMIERUNG 7 ========== + End If + Catch ex As Exception + MyValidationLogger.Error(ex) + MyValidationLogger.Info(">> Unexpected Error In FillIndexValues(GridControl " & oMyGridControl.Name & ") " & ex.Message, True) + MyValidationLogger.Info(">> Controltype " & oControlType) + MyValidationLogger.Info(">> Attributname " & oIndexName) + errormessage = "Unexpected Error In FillIndexValues(Combobox " & oMyGridControl.Name & ") " & vbNewLine & ex.Message & vbNewLine & "Check Logfile" + My.Settings.Save() + frmError.ShowDialog() + End Try - Case oControl.GetType = GetType(CheckBox) - MyValidationLogger.Debug("Loading checkbox...") - oControlType = "CheckBox" - If oSourceIndexName = "" Then - MsgBox("Attention wrong configuration" & vbNewLine & "For control " & oControl.Name & " no INDEX configured!" & vbNewLine & "Bitte prüfen Sie den Formulardesigner!", MsgBoxStyle.Critical, ADDITIONAL_TITLE) - Exit For + Case oControl.GetType = GetType(CheckBox) + MyValidationLogger.Debug("Loading checkbox...") + oControlType = "CheckBox" + If oSourceIndexName = "" Then + MsgBox("Attention wrong configuration" & vbNewLine & "For control " & oControl.Name & " no INDEX configured!" & vbNewLine & "Bitte prüfen Sie den Formulardesigner!", MsgBoxStyle.Critical, ADDITIONAL_TITLE) + Exit For + End If + If oSourceIndexName Is Nothing = False Then + Dim myCheckBox As CheckBox = oControl + + If oLoadIndex = False Or {"@@DISPLAY_ONLY", "DD PM-ONLY For DISPLAY"}.Contains(oSourceIndexName) Then + MyValidationLogger.Debug($" oControl {oControl.Name} Indexwert soll nicht geladen werden.") + Exit Select End If - If oSourceIndexName Is Nothing = False Then - Dim myCheckBox As CheckBox = oControl - If oLoadIndex = False Or {"@@DISPLAY_ONLY", "DD PM-ONLY For DISPLAY"}.Contains(oSourceIndexName) Then - MyValidationLogger.Debug($" oControl {oControl.Name} Indexwert soll nicht geladen werden.") - Exit Select - End If + MyValidationLogger.Debug("Loading Bool-Value from Source...") - MyValidationLogger.Debug("Loading Bool-Value from Source...") + If oSourceIndexName.StartsWith("[%VKT") And PROFIL_VEKTORINDEX <> "" Then + oValueFromSource = ReturnVektor_IndexValue(oSourceIndexName) + Else + Try + MyValidationLogger.Debug($"..Now GetVariableValue({oSourceIndexName})...") + oValueFromSource = GetVariableValuefromSource(oSourceIndexName, oIDBTyp, oIDBOverride) + Catch ex As Exception + MyValidationLogger.Warn($"Could Not Get the windreamValue For CheckboxIndex {oSourceIndexName} [{ex.Message}]") + End Try + End If - If oSourceIndexName.StartsWith("[%VKT") And PROFIL_VEKTORINDEX <> "" Then - oValueFromSource = ReturnVektor_IndexValue(oSourceIndexName) + If oValueFromSource Is Nothing Then + MyValidationLogger.Info(">> Zurückgegebener Wert des Wertes für Checkbox mit Indexname '" & oIndexName & "' ist nothing. Checking defaultvalue") + MyValidationLogger.Debug(">> Zurückgegebener Wert des Wertes für Checkbox mit Indexname '" & oIndexName & "' ist nothing. Checking defaultvalue") + If oDefaultValue <> String.Empty Then + MyValidationLogger.Info($"Using Default value [{oDefaultValue}]") + MyValidationLogger.Debug($"Using Default value [{oDefaultValue}]") + myCheckBox.Checked = CBool(oDefaultValue) + Exit Select Else - Try - MyValidationLogger.Debug($"..Now GetVariableValue({oSourceIndexName})...") - oValueFromSource = GetVariableValuefromSource(oSourceIndexName, oIDBTyp, oIDBOverride) - Catch ex As Exception - MyValidationLogger.Warn($"Could Not Get the windreamValue For CheckboxIndex {oSourceIndexName} [{ex.Message}]") - End Try + MyValidationLogger.Debug("No Default Value for Checkbox - so using false!") + myCheckBox.CheckState = CheckState.Indeterminate End If - - If oValueFromSource Is Nothing Then - MyValidationLogger.Info(">> Zurückgegebener Wert des Wertes für Checkbox mit Indexname '" & oIndexName & "' ist nothing. Checking defaultvalue") - MyValidationLogger.Debug(">> Zurückgegebener Wert des Wertes für Checkbox mit Indexname '" & oIndexName & "' ist nothing. Checking defaultvalue") + Else + MyValidationLogger.Debug("oValueFromSource: " & oValueFromSource.ToString) + If oValueFromSource.ToString = "" Then + MyValidationLogger.Info(">> Versuch, default Value zu laden") If oDefaultValue <> String.Empty Then - MyValidationLogger.Info($"Using Default value [{oDefaultValue}]") - MyValidationLogger.Debug($"Using Default value [{oDefaultValue}]") - myCheckBox.Checked = CBool(oDefaultValue) - Exit Select - Else - MyValidationLogger.Debug("No Default Value for Checkbox - so using false!") - myCheckBox.CheckState = CheckState.Indeterminate - End If - Else - MyValidationLogger.Debug("oValueFromSource: " & oValueFromSource.ToString) - If oValueFromSource.ToString = "" Then - MyValidationLogger.Info(">> Versuch, default Value zu laden") - If oDefaultValue <> String.Empty Then - Dim result = False - If Boolean.TryParse(oDefaultValue, result) Then - MyValidationLogger.Info(">> defaultValue wurde geladen") - myCheckBox.Checked = result - myCheckBox.CheckState = If(result, CheckState.Checked, CheckState.Unchecked) - Else - myCheckBox.Checked = False - myCheckBox.CheckState = CheckState.Unchecked - End If + Dim result = False + If Boolean.TryParse(oDefaultValue, result) Then + MyValidationLogger.Info(">> defaultValue wurde geladen") + myCheckBox.Checked = result + myCheckBox.CheckState = If(result, CheckState.Checked, CheckState.Unchecked) Else - MyValidationLogger.Info(">> defaultValue war leer") myCheckBox.Checked = False myCheckBox.CheckState = CheckState.Unchecked End If Else - Dim _value - If oValueFromSource.ToString = "System.Object[]" Then - MyValidationLogger.Debug("CheckBoxValue with VectorField: " & oSourceIndexName) - If oValueFromSource.length = 1 Then - _value = oValueFromSource(0) - Else - MyValidationLogger.Info(" >> Vectorfield " & oSourceIndexName & "' contains more then one value - First value will be used") - _value = oValueFromSource(0) - End If + MyValidationLogger.Info(">> defaultValue war leer") + myCheckBox.Checked = False + myCheckBox.CheckState = CheckState.Unchecked + End If + Else + Dim _value + If oValueFromSource.ToString = "System.Object[]" Then + MyValidationLogger.Debug("CheckBoxValue with VectorField: " & oSourceIndexName) + If oValueFromSource.length = 1 Then + _value = oValueFromSource(0) Else - _value = oValueFromSource - MyValidationLogger.Debug($"Value is not nothing and also not System.Object: [{_value}]") + MyValidationLogger.Info(" >> Vectorfield " & oSourceIndexName & "' contains more then one value - First value will be used") + _value = oValueFromSource(0) End If - Try - Select Case CBool(_value) - Case True - MyValidationLogger.Debug(">> CBool(_value) = True") - myCheckBox.Checked = True - myCheckBox.CheckState = CheckState.Checked - Case False - MyValidationLogger.Debug(">> CBool(_value) = False") - myCheckBox.Checked = False - myCheckBox.CheckState = CheckState.Unchecked - End Select - Catch ex As Exception - MyValidationLogger.Error(ex) - MyValidationLogger.Info("Unexpected error in CBool(wertWD) - CheckBox: " & ex.Message & vbNewLine & "Wert WD: " & oValueFromSource.ToString, True) - myCheckBox.Checked = False - myCheckBox.CheckState = CheckState.Unchecked - End Try + Else + _value = oValueFromSource + MyValidationLogger.Debug($"Value is not nothing and also not System.Object: [{_value}]") End If + Try + Select Case CBool(_value) + Case True + MyValidationLogger.Debug(">> CBool(_value) = True") + myCheckBox.Checked = True + myCheckBox.CheckState = CheckState.Checked + Case False + MyValidationLogger.Debug(">> CBool(_value) = False") + myCheckBox.Checked = False + myCheckBox.CheckState = CheckState.Unchecked + End Select + Catch ex As Exception + MyValidationLogger.Error(ex) + MyValidationLogger.Info("Unexpected error in CBool(wertWD) - CheckBox: " & ex.Message & vbNewLine & "Wert WD: " & oValueFromSource.ToString, True) + myCheckBox.Checked = False + myCheckBox.CheckState = CheckState.Unchecked + End Try End If End If + End If - Case oControl.GetType = GetType(LookupControl3) - If LOG_PERF Then PerformanceLogger.Info("FillIndexValues/LookupControl") + Case oControl.GetType = GetType(LookupControl3) + If LOG_PERF Then PerformanceLogger.Info("FillIndexValues/LookupControl") + Try + Dim oLookup As LookupControl3 = oControl + Dim oLookupMeta As ClassControlCreator.ControlMetadata = DirectCast(oLookup.Tag, ClassControlCreator.ControlMetadata) - Try - Dim oLookup As LookupControl3 = oControl - oValueFromSource = GetVariableValuefromSource(oSourceIndexName, oIDBTyp, oIDBOverride) + ' ========== BUGFIX START: Alte SelectedValues SICHERN bevor DataSource überschrieben wird ========== + Dim previousSelectedValues As List(Of String) = Nothing + Dim hadPreviousSelection As Boolean = False - Try - oLookup.Properties.SelectedValues = Nothing - oLookup.Properties.SelectedValues = New List(Of String) - Catch ex As Exception - End Try + If oLookup.Properties.SelectedValues IsNot Nothing AndAlso oLookup.Properties.SelectedValues.Count > 0 Then + previousSelectedValues = New List(Of String)(oLookup.Properties.SelectedValues) + hadPreviousSelection = True + MyValidationLogger.Debug($"[FillIndexValues BUGFIX] Lookup [{oLookupMeta.Name}]: Alte SelectedValues gesichert = [{String.Join(",", previousSelectedValues)}]") + End If + ' ========== BUGFIX END: Sicherung ========== - If Not IsNothing(oValueFromSource) Then - Dim oMyType = oValueFromSource.GetType.ToString - If oMyType.Contains("System.Object") Or oMyType = "System.Data.DataTable" Then - Dim oArrlist As New List(Of String) - If IDB_ACTIVE = False Then - For Each oVectorRow As Object In oValueFromSource - Dim Ocontent = oVectorRow.ToString - oArrlist.Add(Ocontent) - Next - Else - Dim myDT As DataTable = oValueFromSource - For Each oVectorRow As DataRow In myDT.Rows - Dim Ocontent = oVectorRow.Item(0) - oArrlist.Add(Ocontent) - Next - End If - oLookup.Properties.SelectedValues = oArrlist + oValueFromSource = GetVariableValuefromSource(oSourceIndexName, oIDBTyp, oIDBOverride) + + If oLoadIndex = False Then + MyValidationLogger.Debug($" oLookup {oLookup.Name}: Indexwert soll nicht geladen werden.") + Exit Select + End If + + Dim oNewValues As List(Of String) = Nothing + + If Not IsNothing(oValueFromSource) Then + Dim oMyType = oValueFromSource.GetType.ToString + If oMyType.Contains("System.Object") Or oMyType = "System.Data.DataTable" Then + Dim oArrlist As New List(Of String) + If IDB_ACTIVE = False Then + For Each oVectorRow As Object In oValueFromSource + Dim Ocontent = oVectorRow.ToString + oArrlist.Add(Ocontent) + Next Else - Dim oArrlist As New List(Of String) - oArrlist.Add(oValueFromSource.ToString) - oLookup.Properties.SelectedValues = oArrlist + Dim myDT As DataTable = oValueFromSource + For Each oVectorRow As DataRow In myDT.Rows + Dim Ocontent = oVectorRow.Item(0) + oArrlist.Add(Ocontent) + Next End If + oNewValues = oArrlist Else - If Not IsNothing(oLookup.Properties.SelectedValues) Then - If oLookup.Properties.SelectedValues.Count = 0 And oDefaultValue <> String.Empty Then - Dim oValues As List(Of String) = oDefaultValue.Split(",").ToList() - oLookup.Properties.SelectedValues = oValues - End If - End If + oNewValues = New List(Of String) From {oValueFromSource.ToString} + End If + Else + ' ========== BUGFIX START: Wenn KEIN neuer Wert, alte Werte behalten ========== + If hadPreviousSelection AndAlso previousSelectedValues IsNot Nothing AndAlso previousSelectedValues.Count > 0 Then + MyValidationLogger.Debug($"[FillIndexValues BUGFIX] Lookup [{oLookupMeta.Name}]: Kein neuer Wert von Quelle → alte Werte BEHALTEN") + oNewValues = previousSelectedValues + ElseIf oDefaultValue <> String.Empty Then + MyValidationLogger.Debug($"[FillIndexValues BUGFIX] Lookup [{oLookupMeta.Name}]: Keine alten Werte, verwende DefaultValue = [{oDefaultValue}]") + oNewValues = oDefaultValue.Split(",").ToList() + Else + MyValidationLogger.Debug($"[FillIndexValues BUGFIX] Lookup [{oLookupMeta.Name}]: KEINE Werte (oValueFromSource=Nothing, oDefaultValue leer, keine vorherigen Werte)") End If + ' ========== BUGFIX END: Wert-Beibehaltung ========== + End If + + ' ========== KRITISCH: DataSource-Backup erstellen BEVOR SelectedValues gelöscht wird ========== + Dim savedDataSource = oLookup.Properties.DataSource + MyValidationLogger.Debug($"[FillIndexValues BUGFIX] Lookup [{oLookupMeta.Name}]: DataSource-Backup erstellt") + + ' ========== KRITISCH: DataSource ZUERST wiederherstellen, DANN SelectedValues leeren ========== + ' Wenn DataSource verloren gegangen sein sollte (z.B. aus LoadSQLData), JETZT wiederherstellen + If oLookup.Properties.DataSource Is Nothing AndAlso savedDataSource IsNot Nothing Then + oLookup.Properties.DataSource = savedDataSource + MyValidationLogger.Debug($"[FillIndexValues BUGFIX] Lookup [{oLookupMeta.Name}]: DataSource wiederhergestellt BEVOR SelectedValues gelöscht") + End If + + ' Jetzt erst SelectedValues leeren (DataSource ist wieder da!) + Try + oLookup.Properties.SelectedValues = New List(Of String) + MyValidationLogger.Debug($"[FillIndexValues BUGFIX] Lookup [{oLookupMeta.Name}]: SelectedValues auf leere Liste zurückgesetzt") Catch ex As Exception - MyValidationLogger.Error(ex) - MyValidationLogger.Info(" - Unvorhergesehener Unexpected error in AddVorschlag_ComboBox - Indexname: " & oIndexName & " - Fehler: " & vbNewLine & ex.Message) - MsgBox(ex.Message, MsgBoxStyle.Critical, "Unvorhergesehener Unexpected error in Add LookupControl3:") + MyValidationLogger.Warn($"[FillIndexValues BUGFIX] Lookup [{oLookupMeta.Name}]: Fehler beim Zurücksetzen SelectedValues: {ex.Message}") End Try - Case oControl.GetType = GetType(DateTimePicker) - oControlType = "DateTimePicker" - Dim DTP As DateTimePicker = oControl - If oSourceIndexName = "" Then - MsgBox("Attention wrong configuration:" & vbNewLine & "for control " & oControl.Name & " no INDEX configured!" & vbNewLine & "Bitte prüfen Sie den Formulardesigner!", MsgBoxStyle.Critical, ADDITIONAL_TITLE) - Exit For + ' Finale SelectedValues setzen + If oNewValues IsNot Nothing Then + oLookup.Properties.SelectedValues = oNewValues + MyValidationLogger.Debug($"[FillIndexValues BUGFIX] Lookup [{oLookupMeta.Name}]: SelectedValues FINAL gesetzt = [{String.Join(",", oNewValues)}]") + Else + MyValidationLogger.Debug($"[FillIndexValues BUGFIX] Lookup [{oLookupMeta.Name}]: oNewValues ist Nothing, SelectedValues bleiben leer") End If - If oSourceIndexName Is Nothing = False Then - Try - If oSourceIndexName.StartsWith("[%VKT") And PROFIL_VEKTORINDEX <> "" Then - MyValidationLogger.Debug("DATE über PM-Vektor holen") - oValueFromSource = ReturnVektor_IndexValue(oSourceIndexName) - MyValidationLogger.Info(">> DTP is """) - Else - oValueFromSource = GetVariableValuefromSource(oSourceIndexName, oIDBTyp, oIDBOverride) - End If - If oValueFromSource Is Nothing Then oValueFromSource = "" - Dim tempdate As Date = CDate("01.01.0001 00:00:00") - If oValueFromSource.ToString.Length > 0 Then - Try - tempdate = CDate(oValueFromSource) - MyValidationLogger.Debug("DATE konnte umgewandelt werden") - Catch ex As Exception - MyValidationLogger.Error(ex) - MyValidationLogger.Debug("DATE wurde auf heute gesetzt") - End Try - DTP.Text = tempdate - Else - MyValidationLogger.Debug("DATE ist leer") - DTP.Text = tempdate - End If - Catch ex As Exception - MyValidationLogger.Error(ex) - errormessage = "Unvorhergesehener Fehler bei DTP: " & vbNewLine & ex.Message - MyValidationLogger.Info("Unexpected error in FillIndex DTP: " & ex.Message & vbNewLine & "Wert WD: " & oValueFromSource.ToString & vbNewLine & "Indexname: " & oSourceIndexName, True) - frmError.ShowDialog() - MyValidationLogger.Info("Unexpected error in FillIndex DTP: " & ex.Message, True) - End Try - End If - End Select - oCount += 1 - Next + Catch ex As Exception + MyValidationLogger.Error(ex) + MyValidationLogger.Info(" - Unvorhergesehener Unexpected error in FillIndexValues LookupControl3 - Indexname: " & oIndexName & " - Fehler: " & vbNewLine & ex.Message) + MsgBox(ex.Message, MsgBoxStyle.Critical, "Unvorhergesehener Unexpected error in Add LookupControl3:") + End Try + + Case oControl.GetType = GetType(DateTimePicker) + oControlType = "DateTimePicker" + Dim DTP As DateTimePicker = oControl + If oSourceIndexName = "" Then + MsgBox("Attention wrong configuration:" & vbNewLine & "for control " & oControl.Name & " no INDEX configured!" & vbNewLine & "Bitte prüfen Sie den Formulardesigner!", MsgBoxStyle.Critical, ADDITIONAL_TITLE) + Exit For + End If + If oSourceIndexName Is Nothing = False Then + Try + If oSourceIndexName.StartsWith("[%VKT") And PROFIL_VEKTORINDEX <> "" Then + MyValidationLogger.Debug("DATE über PM-Vektor holen") + oValueFromSource = ReturnVektor_IndexValue(oSourceIndexName) + MyValidationLogger.Info(">> DTP is """) + Else + oValueFromSource = GetVariableValuefromSource(oSourceIndexName, oIDBTyp, oIDBOverride) + End If + + If oValueFromSource Is Nothing Then oValueFromSource = "" + Dim tempdate As Date = CDate("01.01.0001 00:00:00") + If oValueFromSource.ToString.Length > 0 Then + Try + tempdate = CDate(oValueFromSource) + MyValidationLogger.Debug("DATE konnte umgewandelt werden") + Catch ex As Exception + MyValidationLogger.Error(ex) + MyValidationLogger.Debug("DATE wurde auf heute gesetzt") + End Try + DTP.Text = tempdate + Else + MyValidationLogger.Debug("DATE ist leer") + DTP.Text = tempdate + End If + Catch ex As Exception + MyValidationLogger.Error(ex) + errormessage = "Unvorhergesehener Fehler bei DTP: " & vbNewLine & ex.Message + MyValidationLogger.Info("Unexpected error in FillIndex DTP: " & ex.Message & vbNewLine & "Wert WD: " & oValueFromSource.ToString & vbNewLine & "Indexname: " & oSourceIndexName, True) + frmError.ShowDialog() + MyValidationLogger.Info("Unexpected error in FillIndex DTP: " & ex.Message, True) + End Try + End If + End Select + oCount += 1 + Next - If LOG_HOTSPOTS Then - MyValidationLogger.Info($"[PERF FillIndexValues] Nach Control-Schleife: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") - perfLastCheck = DateTime.Now - End If + If LOG_HOTSPOTS Then + MyValidationLogger.Info($"[PERF FillIndexValues] Nach Control-Schleife: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") + perfLastCheck = DateTime.Now + End If - Focus_FirstControl() + Focus_FirstControl() - ' ========== OPTIMIERUNG 8: Grid-Dropdown-Columns nur EINMAL am Ende ========== - ' VORHER: Wurde potenziell mehrfach aufgerufen - ' NACHHER: Nur einmal nach allen Control-Updates - Try - Dim oDataTable As DataTable = DT_COLUMNS_GRID_WITH_SQL.Clone() - DT_COLUMNS_GRID_WITH_SQL.Select($"SQL_COMMAND not like '%#CTRL#%'").CopyToDataTable(oDataTable, LoadOption.PreserveChanges) - - ' ========== OPTIMIERUNG 9: Control-Suche mit Dictionary ========== - ' VORHER: Für jede Row wurde über alle Controls geloopt - ' NACHHER: Dictionary-Lookup - For Each oRow As DataRow In oDataTable.Rows - Dim oDEPENDING_CTRL_ID = CInt(oRow.Item("CONTROL_ID")) - Dim oDEPENDING_COLUMN = oRow.Item("SPALTENNAME") - Dim oSqlCommand = oRow.Item("SQL_COMMAND") - Dim oCONNID = oRow.Item("CONNECTION_ID") - Dim oAdvancedLookup = oRow.Item("ADVANCED_LOOKUP") - oSqlCommand = clsPatterns.ReplaceAllValues(oSqlCommand, PanelValidatorControl, True) + ' ========== OPTIMIERUNG 8: Grid-Dropdown-Columns nur EINMAL am Ende ========== + ' VORHER: Wurde potenziell mehrfach aufgerufen + ' NACHHER: Nur einmal nach allen Control-Updates + Try + Dim oDataTable As DataTable = DT_COLUMNS_GRID_WITH_SQL.Clone() + DT_COLUMNS_GRID_WITH_SQL.Select($"SQL_COMMAND not like '%#CTRL#%'").CopyToDataTable(oDataTable, LoadOption.PreserveChanges) + + ' ========== OPTIMIERUNG 9: Control-Suche mit Dictionary ========== + ' VORHER: Für jede Row wurde über alle Controls geloopt + ' NACHHER: Dictionary-Lookup + For Each oRow As DataRow In oDataTable.Rows + Dim oDEPENDING_CTRL_ID = CInt(oRow.Item("CONTROL_ID")) + Dim oDEPENDING_COLUMN = oRow.Item("SPALTENNAME") + Dim oSqlCommand = oRow.Item("SQL_COMMAND") + Dim oCONNID = oRow.Item("CONNECTION_ID") + Dim oAdvancedLookup = oRow.Item("ADVANCED_LOOKUP") + oSqlCommand = clsPatterns.ReplaceAllValues(oSqlCommand, PanelValidatorControl, True) - Try - Dim oDTRESULT_FOR_COLUMN As DataTable = GetCachedDatatable(oSqlCommand, oCONNID) + Try + Dim oDTRESULT_FOR_COLUMN As DataTable = GetCachedDatatable(oSqlCommand, oCONNID) - If Not IsNothing(oDTRESULT_FOR_COLUMN) Then - MyValidationLogger.Debug($"Trying to create a DropDown(FIV) for CONTROL-ID [{oDEPENDING_CTRL_ID}] - RowCount: [{oDTRESULT_FOR_COLUMN.Rows.Count}] ") + If Not IsNothing(oDTRESULT_FOR_COLUMN) Then + MyValidationLogger.Debug($"Trying to create a DropDown(FIV) for CONTROL-ID [{oDEPENDING_CTRL_ID}] - RowCount: [{oDTRESULT_FOR_COLUMN.Rows.Count}] ") - ' Dictionary-Lookup statt Loop - Dim oControl As Control = Nothing - If _CachedControlsByGuid.TryGetValue(oDEPENDING_CTRL_ID, oControl) Then - ControlCreator.GridTables_CacheDatatableForColumn(oDEPENDING_CTRL_ID, oDEPENDING_COLUMN, oSqlCommand, oCONNID, oAdvancedLookup) - Else - MyValidationLogger.Warn($"Control mit ID {oDEPENDING_CTRL_ID} nicht gefunden!") - End If + ' Dictionary-Lookup statt Loop + Dim oControl As Control = Nothing + If _CachedControlsByGuid.TryGetValue(oDEPENDING_CTRL_ID, oControl) Then + ControlCreator.GridTables_CacheDatatableForColumn(oDEPENDING_CTRL_ID, oDEPENDING_COLUMN, oSqlCommand, oCONNID, oAdvancedLookup) Else - MyValidationLogger.Warn($"FillIndexValues - oDTRESULT_FOR_COLUMN is nothing!") + MyValidationLogger.Warn($"Control mit ID {oDEPENDING_CTRL_ID} nicht gefunden!") End If - Catch ex As Exception - MyValidationLogger.Warn($"FillIndexValues - Unexpected error in creating Grid-Dropdown-Column [{oDEPENDING_COLUMN}] for CONTROL-ID [{oDEPENDING_CTRL_ID}]: " & ex.Message) - End Try - Next - Catch ex As Exception - MyValidationLogger.Warn($"FillIndexValues - Unexpected error in creating dropdown for Grid: " & ex.Message) - End Try - ' ========== ENDE OPTIMIERUNG 8+9 ========== + Else + MyValidationLogger.Warn($"FillIndexValues - oDTRESULT_FOR_COLUMN is nothing!") + End If + Catch ex As Exception + MyValidationLogger.Warn($"FillIndexValues - Unexpected error in creating Grid-Dropdown-Column [{oDEPENDING_COLUMN}] for CONTROL-ID [{oDEPENDING_CTRL_ID}]: " & ex.Message) + End Try + Next + Catch ex As Exception + MyValidationLogger.Warn($"FillIndexValues - Unexpected error in creating dropdown for Grid: " & ex.Message) + End Try + ' ========== ENDE OPTIMIERUNG 8+9 ========== - If LOG_HOTSPOTS Then - MyValidationLogger.Info($"[PERF FillIndexValues] Nach Grid-Dropdown-Loop: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") - perfLastCheck = DateTime.Now - End If + If LOG_HOTSPOTS Then + MyValidationLogger.Info($"[PERF FillIndexValues] Nach Grid-Dropdown-Loop: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") + perfLastCheck = DateTime.Now + End If - If LOG_PERF Then PerformanceLogger.Info("FillIndexValues/Postload") + If LOG_PERF Then PerformanceLogger.Info("FillIndexValues/Postload") - ' IDB PM_Info Setup (bleibt gleich) - If IDB_ACTIVE = True Then - Try - Dim oSQL = $"select Attribut, TERM_VALUE from VWIDB_VALUE_TEXT WHERE LANG_CODE IN ('{USER_LANGUAGE}','UNQID') AND IDB_OBJ_ID = {CURRENT_DOC_ID} AND Attribut in ('PM_Info1','PM_Info2') ORDER BY Attribut" - Dim oDTINFO As DataTable = DatabaseFallback.GetDatatableIDB(oSQL) - If Not IsNothing(oDTINFO) Then - Dim oColor As System.Drawing.Color - If oDTINFO.Rows.Count > 0 Then - Dim oColumns As String() - If oDTINFO.Rows.Count = 1 Then - oColumns = Split(oDTINFO.Rows(0).Item("TERM_VALUE"), "#") - If oColumns.Length = 1 Then - bsiInfo1.Caption = oDTINFO.Rows(0).Item("TERM_VALUE") - ElseIf oColumns.Length = 2 Then - bsiInfo1.Caption = oColumns(0) - Try - oColor = System.Drawing.Color.FromName(oColumns(1)) - bsiInfo1.ItemAppearance.Normal.ForeColor = oColor - Catch ex As Exception - End Try - End If - bsiInfo2.Visibility = BarItemVisibility.Never - ElseIf oDTINFO.Rows.Count = 2 Then - oColumns = Split(oDTINFO.Rows(0).Item("TERM_VALUE"), "#") - If oColumns.Length = 1 Then - bsiInfo1.Caption = oDTINFO.Rows(0).Item("TERM_VALUE") - ElseIf oColumns.Length = 2 Then - bsiInfo1.Caption = oColumns(0) - Try - oColor = System.Drawing.Color.FromName(oColumns(1)) - bsiInfo1.ItemAppearance.Normal.ForeColor = oColor - Catch ex As Exception - End Try - End If + ' IDB PM_Info Setup (bleibt gleich) + If IDB_ACTIVE = True Then + Try + Dim oSQL = $"select Attribut, TERM_VALUE from VWIDB_VALUE_TEXT WHERE LANG_CODE IN ('{USER_LANGUAGE}','UNQID') AND IDB_OBJ_ID = {CURRENT_DOC_ID} AND Attribut in ('PM_Info1','PM_Info2') ORDER BY Attribut" + Dim oDTINFO As DataTable = DatabaseFallback.GetDatatableIDB(oSQL) + If Not IsNothing(oDTINFO) Then + Dim oColor As System.Drawing.Color + If oDTINFO.Rows.Count > 0 Then + Dim oColumns As String() + If oDTINFO.Rows.Count = 1 Then + oColumns = Split(oDTINFO.Rows(0).Item("TERM_VALUE"), "#") + If oColumns.Length = 1 Then + bsiInfo1.Caption = oDTINFO.Rows(0).Item("TERM_VALUE") + ElseIf oColumns.Length = 2 Then + bsiInfo1.Caption = oColumns(0) + Try + oColor = System.Drawing.Color.FromName(oColumns(1)) + bsiInfo1.ItemAppearance.Normal.ForeColor = oColor + Catch ex As Exception + End Try + End If + bsiInfo2.Visibility = BarItemVisibility.Never + ElseIf oDTINFO.Rows.Count = 2 Then + oColumns = Split(oDTINFO.Rows(0).Item("TERM_VALUE"), "#") + If oColumns.Length = 1 Then + bsiInfo1.Caption = oDTINFO.Rows(0).Item("TERM_VALUE") + ElseIf oColumns.Length = 2 Then + bsiInfo1.Caption = oColumns(0) + Try + oColor = System.Drawing.Color.FromName(oColumns(1)) + bsiInfo1.ItemAppearance.Normal.ForeColor = oColor + Catch ex As Exception + End Try + End If - oColumns = Split(oDTINFO.Rows(1).Item("TERM_VALUE"), "#") - If oColumns.Length = 1 Then - bsiInfo2.Caption = oDTINFO.Rows(1).Item("TERM_VALUE") - ElseIf oColumns.Length = 2 Then - bsiInfo2.Caption = oColumns(0) - Try - oColor = System.Drawing.Color.FromName(oColumns(1)) - bsiInfo2.ItemAppearance.Normal.ForeColor = oColor - Catch ex As Exception - End Try - End If - bsiInfo2.Visibility = BarItemVisibility.Always + oColumns = Split(oDTINFO.Rows(1).Item("TERM_VALUE"), "#") + If oColumns.Length = 1 Then + bsiInfo2.Caption = oDTINFO.Rows(1).Item("TERM_VALUE") + ElseIf oColumns.Length = 2 Then + bsiInfo2.Caption = oColumns(0) + Try + oColor = System.Drawing.Color.FromName(oColumns(1)) + bsiInfo2.ItemAppearance.Normal.ForeColor = oColor + Catch ex As Exception + End Try End If - RibbonPageGroup2.Visible = True - Else - MyValidationLogger.Debug($"No PM_Info-Configuration!!") - RibbonPageGroup2.Visible = False + bsiInfo2.Visibility = BarItemVisibility.Always End If + RibbonPageGroup2.Visible = True Else - MyValidationLogger.Warn($"oDTINFO is nothing!!") + MyValidationLogger.Debug($"No PM_Info-Configuration!!") RibbonPageGroup2.Visible = False End If - Catch ex As Exception - MyValidationLogger.Warn($"Unexpected error in Setting PMINFO - ERROR: {ex.Message}") + Else + MyValidationLogger.Warn($"oDTINFO is nothing!!") RibbonPageGroup2.Visible = False - End Try - Else + End If + Catch ex As Exception + MyValidationLogger.Warn($"Unexpected error in Setting PMINFO - ERROR: {ex.Message}") RibbonPageGroup2.Visible = False - End If - - If LOG_HOTSPOTS Then - MyValidationLogger.Info($"[PERF FillIndexValues] Nach PM_Info-Setup: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") - perfLastCheck = DateTime.Now - End If + End Try + Else + RibbonPageGroup2.Visible = False + End If - _Indexe_Loaded = True + If LOG_HOTSPOTS Then + MyValidationLogger.Info($"[PERF FillIndexValues] Nach PM_Info-Setup: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") + perfLastCheck = DateTime.Now + End If - Load_Additional_Searches(Not CONFIG.Config.ADDITIONAL_SEARCHES_LOAD_ONCLICK) + _Indexe_Loaded = True - If LOG_HOTSPOTS Then - MyValidationLogger.Info($"[PERF FillIndexValues] Nach Load_Additional_Searches: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") - perfLastCheck = DateTime.Now - End If + Load_Additional_Searches(Not CONFIG.Config.ADDITIONAL_SEARCHES_LOAD_ONCLICK) - If CONFIG.Config.ADDITIONAL_SEARCHES_LOAD_ONCLICK = False And (AdditionalDocResultsExist = True Or AdditionalDataResultsExist = True) Then - TryOpen_Additional_Searches() - End If + If LOG_HOTSPOTS Then + MyValidationLogger.Info($"[PERF FillIndexValues] Nach Load_Additional_Searches: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") + perfLastCheck = DateTime.Now + End If - If LOG_HOTSPOTS Then - MyValidationLogger.Info($"[PERF FillIndexValues] Nach TryOpen_Additional_Searches: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") - perfLastCheck = DateTime.Now - End If + If CONFIG.Config.ADDITIONAL_SEARCHES_LOAD_ONCLICK = False And (AdditionalDocResultsExist = True Or AdditionalDataResultsExist = True) Then + TryOpen_Additional_Searches() + End If - Else - MsgBox("No Form-Mask defined for this profile!" & vbNewLine & "Please inform Your admin!" & vbNewLine & "The validator will be closed!", MsgBoxStyle.Exclamation, "Attention:") - Me.Close() + If LOG_HOTSPOTS Then + MyValidationLogger.Info($"[PERF FillIndexValues] Nach TryOpen_Additional_Searches: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") + perfLastCheck = DateTime.Now End If - Catch ex As Exception - MyValidationLogger.Warn($"Unexpected error in FillIndexValues: [{oControName} -TYPE: {oControlType}-INDEXNAME: {oIndexName}] ERROR: {ex.Message}") - errormessage = $"Unexpected error in FillIndexValues: [{oControName} -TYPE: {oControlType}-INDEXNAME: {oIndexName}] ERROR: {ex.Message}" & vbNewLine & "Check Logfile" - My.Settings.Save() - frmError.ShowDialog() - Finally - ' ========== OPTIMIERUNG 10: UI-Updates wieder aktivieren ========== - ' KRITISCH: Erst HIER wird das Panel neu gezeichnet → nur EINMAL statt tausende Male - PanelValidatorControl.ResumeLayout() - ' ========== ENDE OPTIMIERUNG 10 ========== + Else + MsgBox("No Form-Mask defined for this profile!" & vbNewLine & "Please inform Your admin!" & vbNewLine & "The validator will be closed!", MsgBoxStyle.Exclamation, "Attention:") + Me.Close() + End If - ' ========== OPTIMIERUNG 11: GridTables nur EINMAL am Ende ========== - ' VORHER: War im TextBox-Case drin → wurde für jede TextBox aufgerufen - ' NACHHER: Nur noch EINMAL am Ende → massive Zeitersparnis - Try - ControlCreator.GridTables_HandleControlValueChange(PanelValidatorControl, DT_COLUMNS_GRID_WITH_SQL_WITH_CTRL_PLACEHOLDER) - Catch ex As Exception - MyValidationLogger.Warn($"GridTables_HandleControlValueChange Fehler: {ex.Message}") - End Try - ' ========== ENDE OPTIMIERUNG 11 ========== + Catch ex As Exception + MyValidationLogger.Warn($"Unexpected error in FillIndexValues: [{oControName} -TYPE: {oControlType}-INDEXNAME: {oIndexName}] ERROR: {ex.Message}") + errormessage = $"Unexpected error in FillIndexValues: [{oControName} -TYPE: {oControlType}-INDEXNAME: {oIndexName}] ERROR: {ex.Message}" & vbNewLine & "Check Logfile" + My.Settings.Save() + frmError.ShowDialog() + Finally + _suppressLookupEvents = False ' ← NEU: Events wieder freigeben + ' KRITISCH: Erst HIER wird das Panel neu gezeichnet → nur EINMAL statt tausende Male + PanelValidatorControl.ResumeLayout() + ' ========== ENDE OPTIMIERUNG 10 ========== + + ' ========== OPTIMIERUNG 11: GridTables nur EINMAL am Ende ========== + ' VORHER: War im TextBox-Case drin → wurde für jede TextBox aufgerufen + ' NACHHER: Nur noch EINMAL am Ende → massive Zeitersparnis + Try + ControlCreator.GridTables_HandleControlValueChange(PanelValidatorControl, DT_COLUMNS_GRID_WITH_SQL_WITH_CTRL_PLACEHOLDER) + Catch ex As Exception + MyValidationLogger.Warn($"GridTables_HandleControlValueChange Fehler: {ex.Message}") + End Try + ' ========== ENDE OPTIMIERUNG 11 ========== - If LOG_HOTSPOTS Then - Dim totalMs = (DateTime.Now - perfStart).TotalMilliseconds - If totalMs > 6000 Then - MyValidationLogger.Warn($"[PERF FillIndexValues] ⚠️ GESAMT LANGSAM: {totalMs}ms (Schwellwert: 6000ms)") - Else - MyValidationLogger.Info($"[PERF FillIndexValues] GESAMT: {totalMs}ms") - End If + If LOG_HOTSPOTS Then + Dim totalMs = (DateTime.Now - perfStart).TotalMilliseconds + If totalMs > 6000 Then + MyValidationLogger.Warn($"[PERF FillIndexValues] ⚠️ GESAMT LANGSAM: {totalMs}ms (Schwellwert: 6000ms)") + Else + MyValidationLogger.Info($"[PERF FillIndexValues] GESAMT: {totalMs}ms") End If - End Try + End If + End Try End Sub Private Sub ApplyCurrencyMask(pTextEdit As TextEdit) @@ -4664,6 +4962,7 @@ Public Class frmValidator End Sub Private Sub frmValidation_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown + Dim oHandle = SplashScreenManager.ShowOverlayForm(Me) Dim perfStart As DateTime = DateTime.MinValue Dim perfLastCheck As DateTime = DateTime.MinValue If LOG_HOTSPOTS Then @@ -4671,104 +4970,124 @@ Public Class frmValidator perfLastCheck = perfStart MyValidationLogger.Info("[PERF] frmValidation_Shown START") End If - ' Refresh_FileList() - Load_Next_Document(True) - If LOG_HOTSPOTS Then - MyValidationLogger.Info($"[PERF] frmValidation_Shown nach Load_Next_Document: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") - perfLastCheck = DateTime.Now - End If + Try - _DependingControl_In_Action = False - _DependingColumn_In_Action = False + ' Refresh_FileList() + Load_Next_Document(True) + If LOG_HOTSPOTS Then + MyValidationLogger.Info($"[PERF] frmValidation_Shown nach Load_Next_Document: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") + perfLastCheck = DateTime.Now + End If - ' 18.10.2021: Brauchen Sie das Überhaupt?? - 'Controls2beDisabled() + _DependingControl_In_Action = False + _DependingColumn_In_Action = False - BringToFront() - If bbtniRefreshSearches.Visibility = BarItemVisibility.Always Then - _frmValidatorSearch?.BringToFront() - End If + ' 18.10.2021: Brauchen Sie das Überhaupt?? + 'Controls2beDisabled() - _FormLoaded = True - Try - If USER_GHOST_MODE_ACTIVE Then - BbtnitmSave.Enabled = False - btnSave.Enabled = False - Else - BbtnitmSave.Enabled = True - btnSave.Enabled = True + BringToFront() + If bbtniRefreshSearches.Visibility = BarItemVisibility.Always Then + _frmValidatorSearch?.BringToFront() End If - Catch ex As Exception - End Try + _FormLoaded = True + Try + If USER_GHOST_MODE_ACTIVE Then + BbtnitmSave.Enabled = False + btnSave.Enabled = False + Else + BbtnitmSave.Enabled = True + btnSave.Enabled = True + End If + Catch ex As Exception - Try - If RibbonPageCustTitle <> "" Then - RibbonPageGroupCustom.Text = RibbonPageCustTitle - RibbonPageGroupCustom.Visible = True - Else - RibbonPageGroupCustom.Visible = False - End If - If Not (IsNothing(WMDocPathWindows) And ActiveWorkflowType = ConstAHWorkflow_BlindFile) Then - If ButtonExport2Folder_Caption <> "" And WMDocPathWindows <> "" Then - MyValidationLogger.Debug("Enabling Export2File, Caption set") - MyValidationLogger.Debug("Button Caption: [{0}]", ButtonExport2Folder_Caption) - MyValidationLogger.Debug("Export root folder: [{0}]", ButtonExport2Folder_RootFolder) + End Try - If File.Exists(WMDocPathWindows) Then - MyValidationLogger.Debug("File exists, Showing Export Button") + Try + If RibbonPageCustTitle <> "" Then + RibbonPageGroupCustom.Text = RibbonPageCustTitle + RibbonPageGroupCustom.Visible = True + Else + RibbonPageGroupCustom.Visible = False + End If + If Not (IsNothing(WMDocPathWindows) And ActiveWorkflowType = ConstAHWorkflow_BlindFile) Then + If ButtonExport2Folder_Caption <> "" And WMDocPathWindows <> "" Then + MyValidationLogger.Debug("Enabling Export2File, Caption set") + MyValidationLogger.Debug("Button Caption: [{0}]", ButtonExport2Folder_Caption) + MyValidationLogger.Debug("Export root folder: [{0}]", ButtonExport2Folder_RootFolder) + + If File.Exists(WMDocPathWindows) Then + MyValidationLogger.Debug("File exists, Showing Export Button") + + barbtnitmExport.Caption = ButtonExport2Folder_Caption + If ButtonExport2Folder_Mode <> String.Empty Then + barbtnitmExport.Tag = ButtonExport2Folder_Mode + End If + barbtnitmExport.Visibility = BarItemVisibility.Always + Try + If ButtonExport2Folder_RootFolder <> "" Then + If Directory.Exists(ButtonExport2Folder_RootFolder) Then + If CONFIG.Config.LastExportPath <> String.Empty Then + MyValidationLogger.Debug("Last export path exists, using as default path") + FolderBrowserDialog1.SelectedPath = CONFIG.Config.LastExportPath + Else + FolderBrowserDialog1.SelectedPath = ButtonExport2Folder_RootFolder + End If - barbtnitmExport.Caption = ButtonExport2Folder_Caption - If ButtonExport2Folder_Mode <> String.Empty Then - barbtnitmExport.Tag = ButtonExport2Folder_Mode - End If - barbtnitmExport.Visibility = BarItemVisibility.Always - Try - If ButtonExport2Folder_RootFolder <> "" Then - If Directory.Exists(ButtonExport2Folder_RootFolder) Then - If CONFIG.Config.LastExportPath <> String.Empty Then - MyValidationLogger.Debug("Last export path exists, using as default path") - FolderBrowserDialog1.SelectedPath = CONFIG.Config.LastExportPath + MyValidationLogger.Debug("Setting default export path to [{0}]", FolderBrowserDialog1.SelectedPath) Else - FolderBrowserDialog1.SelectedPath = ButtonExport2Folder_RootFolder + MyValidationLogger.Warn($"### Dis/Enabale Export2Path - RootFolder {ButtonExport2Folder_RootFolder} not existing or accessible!###") End If - MyValidationLogger.Debug("Setting default export path to [{0}]", FolderBrowserDialog1.SelectedPath) - Else - MyValidationLogger.Warn($"### Dis/Enabale Export2Path - RootFolder {ButtonExport2Folder_RootFolder} not existing or accessible!###") End If + Catch ex As Exception + MyValidationLogger.Warn($"### Error Dis/Enabale Export2Path: {ex.Message} !###") + End Try - End If - Catch ex As Exception - MyValidationLogger.Warn($"### Error Dis/Enabale Export2Path: {ex.Message} !###") - End Try - + End If End If End If - End If - Catch ex As Exception - MyValidationLogger.Error(ex) - End Try - If LOG_HOTSPOTS Then - MyValidationLogger.Info($"[PERF] frmValidation_Shown nach Ribbon/Export Setup: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") - perfLastCheck = DateTime.Now - End If + Catch ex As Exception + MyValidationLogger.Error(ex) + End Try + If LOG_HOTSPOTS Then + MyValidationLogger.Info($"[PERF] frmValidation_Shown nach Ribbon/Export Setup: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") + perfLastCheck = DateTime.Now + End If - MyValidationLogger.Debug("frmValidation_Shown finished!") - If LOG_HOTSPOTS Then - MyValidationLogger.Info($"[PERF] frmValidation_Shown GESAMT: {(DateTime.Now - perfStart).TotalMilliseconds}ms") - End If + MyValidationLogger.Debug("frmValidation_Shown finished!") + If LOG_HOTSPOTS Then + MyValidationLogger.Info($"[PERF] frmValidation_Shown GESAMT: {(DateTime.Now - perfStart).TotalMilliseconds}ms") + End If + Finally + SplashScreenManager.CloseOverlayForm(oHandle) + End Try End Sub Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click - btnSave.Enabled = False - ' TODO: Use when working on Validation - If ForceGridValidation() = True Then - Finish_WFStep() + ' ========== FIX 1: Button-State-Management ========== + If btnSave.Enabled = False Then + MyValidationLogger.Warn("btnSave_Click: Button bereits disabled, Exit Sub") + Exit Sub End If - - btnSave.Enabled = True + btnSave.Enabled = False + ' ========== ENDE FIX 1 ========== + Dim oHandle = SplashScreenManager.ShowOverlayForm(Me) + Try + If ForceGridValidation() = True Then + Finish_WFStep() + End If + Finally + ' ========== FIX 2: Nur Enable wenn Form NICHT schließt ========== + If Not _FormClosing AndAlso Not Me.IsDisposed Then + btnSave.Enabled = True + Else + MyValidationLogger.Debug("btnSave_Click: Form closing, Button bleibt disabled") + End If + SplashScreenManager.CloseOverlayForm(oHandle) + ' ========== ENDE FIX 2 ========== + End Try End Sub Private Function ForceGridValidation() @@ -4782,18 +5101,17 @@ Public Class frmValidator Select oControl).ToList() MyValidationLogger.Debug("Forcing grid Validation") - For Each oGrid As GridControl In oGrids MyValidationLogger.Debug("Validating Grid [{0}]", oGrid.Name) Dim oView As GridView = oGrid.MainView - If oView.RowCount = 0 Then - Continue For - End If - - If DoCellValidation(oView) = False Then - oValidation = False + ' WICHTIG: Leere Grids nicht überspringen, + ' damit das Löschen gespeichert wird. + If oView.RowCount > 0 Then + If DoCellValidation(oView) = False Then + oValidation = False + End If End If MyValidationLogger.Debug("Validation of Grid [{0}] ended with Result: [{1}]", oGrid.Name, oValidation) @@ -4915,6 +5233,13 @@ Public Class frmValidator End Function Sub Finish_WFStep(Optional includeFI As Boolean = True) + Dim oHandle As Object = Nothing + Dim overlayStartedHere As Boolean = False + If Not _overlayActive Then + oHandle = SplashScreenManager.ShowOverlayForm(Me) + _overlayActive = True + overlayStartedHere = True + End If Dim perfStart As DateTime = DateTime.MinValue Dim perfLastCheck As DateTime = DateTime.MinValue If LOG_HOTSPOTS Then @@ -4926,7 +5251,6 @@ Public Class frmValidator MyValidationLogger.Debug("Abschluss für DocID " & CURRENT_DOC_ID & " wird gestartet ...") Dim oErrorOcurred As Boolean = False If OverrideAll = False Then - 'Eingaben auf Form überprüfen If Check_UpdateIndexe() = True Then If LOG_HOTSPOTS Then MyValidationLogger.Info($"[PERF] Finish_WFStep nach Check_UpdateIndexe: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") @@ -4934,6 +5258,10 @@ Public Class frmValidator End If If PROFIL_FINISH_SQL <> String.Empty Then If btnFinish_continue() = False Then + If overlayStartedHere Then + _overlayActive = False + SplashScreenManager.CloseOverlayForm(oHandle) + End If Exit Sub End If End If @@ -4945,11 +5273,9 @@ Public Class frmValidator If includeFI = True Then Try - Dim oDTFinalIndexing As DataTable = _CachedFinalIndexing If oDTFinalIndexing?.Rows.Count > 0 Then - 'Jetzt finale Indexe setzen MyValidationLogger.Debug("FINAL INDEXING STARTING...") For Each oFinalIndexRow As DataRow In oDTFinalIndexing.Rows Dim oValue As String = oFinalIndexRow.Item("VALUE").ToString @@ -4962,7 +5288,7 @@ Public Class frmValidator If IDB_ACTIVE = False Then oIndexType = WINDREAM_MOD.GetIndexType(oFinalIndexRow.Item("INDEXNAME")) End If - If oValue.ToUpper = "SQL-Command".ToUpper Then '###### Indexierung mit variablen SQL ### + If oValue.ToUpper = "SQL-Command".ToUpper Then MyValidationLogger.Debug("Indexing wih dynamic sql...") Dim oGUID = oFinalIndexRow.Item("GUID") Dim oSQLCommand = oFinalIndexRow.Item("SQL_COMMAND") @@ -5003,27 +5329,13 @@ Public Class frmValidator oResultfromSQL = "" Continue For End If - End If End If - - 'If Len(oResultfromSQL) = 0 Then - ' If oContinueOnIndifferentState = False Then - ' errormessage = "Result from SQL is EmptyValue - Check the SQL and the log" - ' My.Settings.Save() - ' frmError.ShowDialog() - ' oErrorOcurred = True - ' Else - ' MyValidationLogger.Warn($"FinalIndexResult from SQL is EmptyValue - AttributeName [{oFinalIndexRow.Item("INDEXNAME")}] - oContinueOnIndifferentState = true, So continuing with next Attribute") - ' Continue For - ' End If - 'End If Else MyValidationLogger.Warn("⚠️ ATTENTION: DYNAMIC VALUE IS NOTHING!") Continue For End If End If - Else If oValue.StartsWith("v") Then Select Case oFinalIndexRow.Item("VALUE").ToString @@ -5050,15 +5362,11 @@ Public Class frmValidator oResult(i) = oRow.Item(0).ToString i += 1 Next - End If MyValidationLogger.Debug($"oIndexType {oIndexType.ToString}") MyValidationLogger.Debug("Now the final indexing...") If oIndexType > 4000 And oIndexType < 5000 Then MyValidationLogger.Debug("...via WMIndexVectofield as its an Vektorfield") - Dim oVektorValue As Object - - 'Hier muss nun separat as Vektorfeld indexiert werden um PreventDuplicates etc abzufangen If WMIndexVectofield(oResult, oFinalIndexRow.Item("INDEXNAME"), oFinalIndexRow.Item("PREVENT_DUPLICATES"), oFinalIndexRow.Item("ALLOW_NEW_VALUES")) = False Then MyValidationLogger.Debug("Final Vektorindex '" & oFinalIndexRow.Item("INDEXNAME").ToString & "' has beens et suxxessfully!") Else @@ -5079,13 +5387,10 @@ Public Class frmValidator If Indexiere_File(CURRENT_WMFILE, oFinalIndexRow.Item("INDEXNAME"), oResult) = True Then oFIResult = True MyValidationLogger.Debug("FINALER INDEX '" & oFinalIndexRow.Item("INDEXNAME") & "' WURDE ERFOLGREICH GESETZT") - - 'Nun das Logging If PROFIL_LOGINDEX <> "" Then Dim logstr = Return_LOGString(oValue, "DDFINALINDEX", oFinalIndexRow.Item("INDEXNAME")) WMIndexVectofield(logstr, PROFIL_LOGINDEX) End If - End If Else If IDBData.SetVariableValue(oFinalIndexRow.Item("INDEXNAME"), oValue) = True Then @@ -5099,7 +5404,6 @@ Public Class frmValidator frmError.ShowDialog() oErrorOcurred = True End If - End If If oErrorOcurred = True Then Exit For @@ -5116,7 +5420,6 @@ Public Class frmValidator perfLastCheck = DateTime.Now End If Try - ''Wenn kein Fehler nach der finalen Indexierung gesetzt wurde If Override = True And Override_SQLCommand <> "" Then DatabaseFallback.ExecuteNonQueryECM(Override_SQLCommand) End If @@ -5138,16 +5441,11 @@ Public Class frmValidator WORK_HISTORY_ENTRY = Nothing End Try - If Not IsNothing(WORK_HISTORY_ENTRY) Then If WORK_HISTORY_ENTRY <> String.Empty Then Dim preg As String = "\[%{1}[a-zA-Z0-9\!\$\&\/\(\)\=\?\,\.\-\;\:_öÖüÜäÄ\#\'\+\*\~\{\}\@\€\<\>\ ]+]{1}" - ' einen Regulären Ausdruck laden Dim regulärerAusdruck As System.Text.RegularExpressions.Regex = New System.Text.RegularExpressions.Regex(preg) - ' die Vorkommen im SQL-String auslesen Dim elemente As System.Text.RegularExpressions.MatchCollection = regulärerAusdruck.Matches(WORK_HISTORY_ENTRY) - '#### - ' alle Vorkommen innerhalb der Namenkonvention durchlaufen For Each element As System.Text.RegularExpressions.Match In elemente Try MyValidationLogger.Debug("element in RegeX WORK_HISTORY_ENTRY: " & element.Value) @@ -5165,7 +5463,6 @@ Public Class frmValidator End Try If DirectCast(oControl.Tag, ClassControlCreator.ControlMetadata).Guid = CTRL_ID Then - '###### Select Case True Case oControl.GetType() = GetType(DevExpress.XtraEditors.TextEdit) Or oControl.GetType() = GetType(MemoEdit) Try @@ -5175,7 +5472,6 @@ Public Class frmValidator MyValidationLogger.Error(ex) value_from_control = String.Empty End Try - Case oControl.GetType() = GetType(System.Windows.Forms.ComboBox) Dim cmb As Windows.Forms.ComboBox = oControl Try @@ -5192,7 +5488,6 @@ Public Class frmValidator MyValidationLogger.Error(ex) value_from_control = String.Empty End Try - Case oControl.GetType() = GetType(System.Windows.Forms.CheckBox) Dim chk As CheckBox = oControl Try @@ -5202,7 +5497,6 @@ Public Class frmValidator value_from_control = String.Empty End Try End Select - End If Next End If @@ -5234,13 +5528,12 @@ Public Class frmValidator Dim ins = String.Format("INSERT INTO TBPM_FILES_WORK_HISTORY (PROFIL_ID, DOC_ID,WORKED_BY,WORKED_WHERE,STATUS_COMMENT) VALUES ({0},{1},'{2}','{3}','{4}')", CURRENT_ProfilGUID, CURRENT_DOC_ID, USER_USERNAME, System.Environment.MachineName, WORK_HISTORY_ENTRY) DatabaseFallback.ExecuteNonQueryECM(ins) Dim oFIsql As String - 'Close_document_viewer() If Not IsNothing(Current_Document) Then If Current_Document.Extension = "pdf" Then If Not IsNothing(WORK_HISTORY_ENTRY) Then If CBool(CURRENT_DT_PROFILE.Rows(0).Item("ANNOTATE_WORK_HISTORY_ENTRY")) = True Then oFIsql = String.Format("SELECT * FROM TBPM_FILES_WORK_HISTORY WHERE GUID = (SELECT MAX(GUID) FROM TBPM_FILES_WORK_HISTORY WHERE PROFIL_ID = {0} AND DOC_ID = {1})", CURRENT_ProfilGUID, CURRENT_DOC_ID) - Dim DT_ENTRY As DataTable = DatabaseFallback.GetDatatableECM(oFIsql) ', "Finish_WFStep2") + Dim DT_ENTRY As DataTable = DatabaseFallback.GetDatatableECM(oFIsql) If Not IsNothing(DT_ENTRY) Then If DT_ENTRY.Rows.Count = 1 Then Dim AnnotationString = DT_ENTRY.Rows(0).Item("WORKED_WHEN") & " " & DT_ENTRY.Rows(0).Item("WORKED_BY") & ": " & DT_ENTRY.Rows(0).Item("STATUS_COMMENT") @@ -5251,7 +5544,7 @@ Public Class frmValidator Dim oAnnotateAllWHEs = CURRENT_DT_PROFILE.Rows(0).Item("ANNOTATE_ALL_WORK_HISTORY_ENTRIES") If CBool(oAnnotateAllWHEs) = True Then oFIsql = String.Format("SELECT * FROM TBPM_FILES_WORK_HISTORY WHERE DOC_ID = {1} ORDER BY GUID", CURRENT_ProfilGUID, CURRENT_DOC_ID) - Dim DT_ENTRIES As DataTable = DatabaseFallback.GetDatatableECM(oFIsql) ', "Finish_WFStep3") + Dim DT_ENTRIES As DataTable = DatabaseFallback.GetDatatableECM(oFIsql) If Not IsNothing(DT_ENTRIES) Then If DT_ENTRIES.Rows.Count > 0 Then Dim AnnotationString As String = "" @@ -5271,8 +5564,6 @@ Public Class frmValidator perfLastCheck = DateTime.Now End If - - 'wenn Move2Folder aktiviert wurde If Move2Folder <> "" And (OPERATION_MODE_FS = ClassConstants.OpModeFS_PWM Or OPERATION_MODE_FS = ClassConstants.OpModeFS_IDBWM) Then idxerr_message = allgFunk.Move2Folder(WMDocPathWindows, Move2Folder, CURRENT_ProfilGUID, WINDREAM_ALLG) If idxerr_message <> "" Then @@ -5287,8 +5578,6 @@ Public Class frmValidator End If End If - - End If Catch ex As Exception @@ -5298,14 +5587,20 @@ Public Class frmValidator frmError.ShowDialog() oErrorOcurred = True MyValidationLogger.Info("Unexpected error in Finish: " & ex.Message, True) + If overlayStartedHere Then + _overlayActive = False + SplashScreenManager.CloseOverlayForm(oHandle) + End If Exit Sub End Try Else - 'lblerror.Visible = True - 'lblerror.Text = errmessage errormessage = oErrMsgMissingInput frmError.ShowDialog() oErrorOcurred = True + If overlayStartedHere Then + _overlayActive = False + SplashScreenManager.CloseOverlayForm(oHandle) + End If Exit Sub End If Else @@ -5319,9 +5614,10 @@ Public Class frmValidator MyValidationLogger.Info($"[PERF] Finish_WFStep nach OverrideAll-SQL: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") perfLastCheck = DateTime.Now End If - ' Wert muss für den nächsten Beleg wieder zurückgesetzt werden. OverrideAll = False + ' Overlay wird weiter unten geschlossen (vor Load_Next_Document bzw. BeginInvoke) End If + If oErrorOcurred = True Then MsgBox("Unhandled error occured in Finish Workflow-Step...Please check your log!", MsgBoxStyle.Exclamation, ADDITIONAL_TITLE) Else @@ -5339,20 +5635,34 @@ Public Class frmValidator If CURRENT_JUMP_DOC_GUID <> 0 Then CURRENT_DOC_GUID = 0 - Me.Close() + MyValidationLogger.Info($"[Finish_WFStep] CURRENT_JUMP_DOC_GUID <> 0 → verzögertes Close()") + If overlayStartedHere Then + _overlayActive = False + SplashScreenManager.CloseOverlayForm(oHandle) + End If + BeginInvoke(New Action(Sub() + If Not Me.IsDisposed Then + MyValidationLogger.Debug("[BeginInvoke] Führe Me.Close() aus") + Me.Close() + Else + MyValidationLogger.Warn("[BeginInvoke] Form bereits disposed, Close() übersprungen") + End If + End Sub)) + Exit Sub Else - 'Das nächste Dokument laden Load_Next_Document(False) + + If overlayStartedHere Then + _overlayActive = False + SplashScreenManager.CloseOverlayForm(oHandle) + End If If LOG_HOTSPOTS Then MyValidationLogger.Info($"[PERF] Finish_WFStep nach Load_Next_Document: {(DateTime.Now - perfLastCheck).TotalMilliseconds}ms") perfLastCheck = DateTime.Now End If - Focus_FirstControl() - End If - btnSave.Enabled = True If LOG_HOTSPOTS Then MyValidationLogger.Info($"[PERF] Finish_WFStep GESAMT: {(DateTime.Now - perfStart).TotalMilliseconds}ms") End If @@ -5497,7 +5807,11 @@ Public Class frmValidator Dim oControlId As String Try Dim oMissing As Boolean = False - + ' ========== BATCH: Sammelmodus starten (nur IDB) ========== + If IDB_ACTIVE Then + IDBData.BeginBatch() + End If + ' ========== ENDE BATCH START ========== ' ========== OPTIMIERUNG: Nur geänderte Controls durchlaufen ========== For Each oControl As Control In Me.PanelValidatorControl.Controls Dim oMeta As ClassControlCreator.ControlMetadata = Nothing @@ -5506,6 +5820,7 @@ Public Class frmValidator Catch Continue For ' Control ohne Metadata überspringen End Try + MyValidationLogger.Debug($"[CHECK_UPDATE] Control: [{oMeta.Name}], Type: [{oControl.GetType().Name}], IsDirty: [{oMeta.IsDirty}]") ' Suche die Control-Definition Dim oControlRow = (From form In DTVWCONTROL_INDEX.AsEnumerable() @@ -6201,6 +6516,11 @@ Public Class frmValidator Case oControl.GetType = GetType(GridControl) Dim oGrid As GridControl = oControl + MyValidationLogger.Debug($"[4] GridControl-Case erreicht: [{oGrid.Name}]") + + ' ========== NEU: Cleanup VOR Validierung ========== + CleanupDeletedRows(oGrid) + ' ========== ENDE NEU ========== Dim oSettings = New ControlSettings() With { .IndexName = oIndexName, .ControlType = GetType(GridControl).ToString, @@ -6223,6 +6543,20 @@ Public Class frmValidator Next ' End For Each oControl + ' ========== BATCH: Gesammelte Statements abfeuern ========== + If IDB_ACTIVE Then + If oMissing = False Then + If Not IDBData.CommitBatch() Then + LOGGER.Warn("CommitBatch failed in Check_UpdateIndexe") + oMissing = True + End If + Else + ' Validierungsfehler → Batch verwerfen + IDBData.RollbackBatch() + End If + End If + ' ========== ENDE BATCH ========== + If oMissing = True Then MyValidationLogger.Warn("⚠️ Check_UpdateIndexe: ERROR or Missing Indexing - returning False") Return False @@ -6313,6 +6647,12 @@ Public Class frmValidator Dim myVektorArr As String() 'Jeden Werte des Datagridviews durchlaufen For Each oRow As DataRow In pGrid.DataSource.Rows + ' ========== NEU: Sicherheits-Guard für Deleted/Detached ========== + If oRow.RowState = DataRowState.Deleted OrElse oRow.RowState = DataRowState.Detached Then + MyValidationLogger.Debug($"Grid [{pSettings.Name}]: Überspringe Zeile mit RowState={oRow.RowState}") + Continue For + End If + ' ========== ENDE NEU ========== Dim exists = False Select Case pSettings.ControlType Case "DevExpress.XtraGrid.GridControl" '"TABLE" @@ -6334,11 +6674,11 @@ Public Class frmValidator Dim normalized As Object = ObjectEx.NotNull(item, String.Empty) If TypeOf normalized Is IFormattable AndAlso Not TypeOf normalized Is String Then Dim provider As IFormatProvider = - If(TypeOf normalized Is Decimal OrElse - TypeOf normalized Is Double OrElse - TypeOf normalized Is Single, - CultureInfo.CurrentCulture, - CultureInfo.InvariantCulture) + If(TypeOf normalized Is Decimal OrElse + TypeOf normalized Is Double OrElse + TypeOf normalized Is Single, + CultureInfo.CurrentCulture, + CultureInfo.InvariantCulture) MyValidationLogger.Debug("Normalizing value [{0}]", normalized.ToString) normalized = DirectCast(normalized, IFormattable).ToString(Nothing, provider) @@ -6403,10 +6743,8 @@ Public Class frmValidator If IDB_ACTIVE = False Then If Indexiere_File(CURRENT_WMFILE, pSettings.IndexName, oValue.ToArray) = False Then pMissing = True - 'oErrorMessage = "Error while indexing der Tabelle - ERROR: " & idxerr_message pMissingMessage = $"Error while indexing table (2) {pGrid.Name} - ERROR: " & idxerr_message MyValidationLogger.Warn(pMissingMessage) - 'Exit For Return False End If Else @@ -6422,7 +6760,6 @@ Public Class frmValidator MyValidationLogger.Debug("(String) User cleared the grid, so data needs to be erased!") IDBData.Delete_AttributeData(CURRENT_DOC_ID, pSettings.IndexName) End If - End If End If @@ -6490,6 +6827,7 @@ Public Class frmValidator End Sub Sub Datei_ueberspringen() + Dim oHandle = SplashScreenManager.ShowOverlayForm(Me) Dim perfStart As DateTime = If(LOG_HOTSPOTS, DateTime.Now, Nothing) Dim perfLastCheck As DateTime = perfStart If LOG_HOTSPOTS Then @@ -6543,6 +6881,7 @@ Public Class frmValidator MyValidationLogger.Error(ex) MsgBox("Fehler bei Überspringen:" & vbNewLine & ex.Message, MsgBoxStyle.Critical) Finally + If LOG_HOTSPOTS Then MyValidationLogger.Info($"[PERF] Datei_ueberspringen GESAMT: {(DateTime.Now - perfStart).TotalMilliseconds}ms") @@ -6551,6 +6890,7 @@ Public Class frmValidator MyValidationLogger.Info($" frmValidator.IsDisposed: {Me.IsDisposed}") ' ========== ENDE DIAGNOSE ========== End If + SplashScreenManager.CloseOverlayForm(oHandle) End Try End Sub @@ -6694,7 +7034,6 @@ Public Class frmValidator btnSave.Enabled = False Finish_WFStep() - btnSave.Enabled = True End If End Sub @@ -6779,14 +7118,22 @@ Public Class frmValidator Load_Additional_Searches(True) End Sub Private Sub bbtniRefresh_ItemClick(sender As Object, e As ItemClickEventArgs) Handles bbtniRefresh.ItemClick - Reload_Controls("") + ' ========== KRITISCH: Events KOMPLETT blockieren während Refresh ========== + _suppressLookupEvents = True + Dim oHandle = SplashScreenManager.ShowOverlayForm(Me) Try - btnSave.Text = Translation_Strings.Speichern___Nächster_Vorgang__F2_ - Catch ex As Exception + Reload_Controls("") + Try + btnSave.Text = Translation_Strings.Speichern___Nächster_Vorgang__F2_ + Catch ex As Exception + End Try + listChangedLookup.Clear() + SetStatusLabel("All Data refreshed", "Yellow") + Finally + _suppressLookupEvents = False ' ← Erst NACH allem wieder freigeben + SplashScreenManager.CloseOverlayForm(oHandle) End Try - listChangedLookup.Clear() - SetStatusLabel("All Data refreshed", "Yellow") End Sub Private Sub bbtniNext_ItemClick(sender As Object, e As ItemClickEventArgs) Handles bbtniNext.ItemClick @@ -6880,20 +7227,40 @@ Public Class frmValidator End Sub Private Sub BbtnItm_ItemClick(sender As Object, e As ItemClickEventArgs) Handles BbtnitmSave.ItemClick - If ForceGridValidation() = True Then - Dim oRESULT As String - 'oRESULT = ClassAllgemeineFunktionen.GUI_LANGUAGE_INFO("InputSaved") - oRESULT = Translation_Strings.Eingaben_gespeichert + ' ========== FIX 1: Button-State-Management ========== + If BbtnitmSave.Enabled = False Then + MyValidationLogger.Warn("BbtnitmSave_ItemClick: Button bereits disabled, Exit Sub") + Exit Sub + End If + BbtnitmSave.Enabled = False + ' ========== ENDE FIX 1 ========== + Dim oHandle = SplashScreenManager.ShowOverlayForm(Me) + Try + ' ========== FIX 2: Nur EINEN Check-Aufruf ========== If Check_UpdateIndexe() = True Then - SetStatusLabel($"Data saved", "LimeGreen") + SetStatusLabel("Data saved", "LimeGreen") MyValidationLogger.Info("Workflowdata saved manually!") - Dim ins = String.Format("INSERT INTO TBPM_FILES_WORK_HISTORY (PROFIL_ID, DOC_ID,WORKED_BY,WORKED_WHERE,STATUS_COMMENT) VALUES ({0},{1},'{2}','{3}','{4}')", CURRENT_ProfilGUID, CURRENT_DOC_ID, USER_USERNAME, System.Environment.MachineName, "Manual Save via button") + + Dim ins = String.Format( + "INSERT INTO TBPM_FILES_WORK_HISTORY (PROFIL_ID, DOC_ID, WORKED_BY, WORKED_WHERE, STATUS_COMMENT) VALUES ({0},{1},'{2}','{3}','{4}')", + CURRENT_ProfilGUID, CURRENT_DOC_ID, USER_USERNAME, System.Environment.MachineName, "Manual Save via button") + DatabaseFallback.ExecuteNonQueryECM(ins) Else - SetStatusLabel($"Error while saving data!", "Red") + SetStatusLabel("Error while saving data!", "Red") End If - End If + ' ========== ENDE FIX 2 ========== + Finally + ' ========== FIX 3: Button nur re-enablen wenn Form nicht schließt ========== + If Not _FormClosing AndAlso Not Me.IsDisposed Then + BbtnitmSave.Enabled = True + Else + MyValidationLogger.Debug("BbtnitmSave_ItemClick: Form closing, Button bleibt disabled") + End If + SplashScreenManager.CloseOverlayForm(oHandle) + ' ========== ENDE FIX 3 ========== + End Try End Sub Private Sub SaveDevExpressGridControl_Layout(pProfilID As Integer, pControlID As Integer, pGridView As DevExpress.XtraGrid.Views.Grid.GridView) Try diff --git a/app/TaskFlow/taskFLOW.vbproj b/app/TaskFlow/taskFLOW.vbproj index a2d23ac..b686d29 100644 --- a/app/TaskFlow/taskFLOW.vbproj +++ b/app/TaskFlow/taskFLOW.vbproj @@ -624,6 +624,12 @@ Form + + frmExpression_Designer.vb + + + Form + frmFileInfo.vb @@ -868,6 +874,9 @@ frmError.vb Designer + + frmExpression_Designer.vb + frmFileInfo.vb Designer