Version 2.8.3 zu Test an MK und HE

This commit is contained in:
Developer01
2026-03-03 12:55:01 +01:00
parent a192267d96
commit 41e46f9dbb
4 changed files with 485 additions and 44 deletions

View File

@@ -25,7 +25,8 @@ Namespace ControlCreator
Private newRowModified As Boolean Private newRowModified As Boolean
Private isApplyingInheritedValue As Boolean Private isApplyingInheritedValue As Boolean
Private _FormulaColumnNames As New HashSet(Of String)(StringComparer.OrdinalIgnoreCase)
Private _isRefreshingFormula As Boolean = False ' *** NEU: Flag für Formel-Refresh ***
Public Sub New(pLogConfig As LogConfig, pGridTables As Dictionary(Of Integer, Dictionary(Of String, RepositoryItem))) Public Sub New(pLogConfig As LogConfig, pGridTables As Dictionary(Of Integer, Dictionary(Of String, RepositoryItem)))
_LogConfig = pLogConfig _LogConfig = pLogConfig
_Logger = pLogConfig.GetLogger() _Logger = pLogConfig.GetLogger()
@@ -315,7 +316,7 @@ Namespace ControlCreator
settings.MaskExpression = "c" settings.MaskExpression = "c"
settings.Culture = oCultureInfo settings.Culture = oCultureInfo
End Sub) End Sub)
riTextEdit.UseMaskAsDisplayFormat = True 'Optional riTextEdit.UseMaskAsDisplayFormat = True
pGrid.RepositoryItems.Add(riTextEdit) pGrid.RepositoryItems.Add(riTextEdit)
For Each oCol As GridColumn In pGridView.Columns For Each oCol As GridColumn In pGridView.Columns
@@ -327,6 +328,14 @@ Namespace ControlCreator
Continue For Continue For
End If End If
' Formel-Spalten dürfen kein ColumnEdit bekommen, da der RepositoryItem-Cache
' den berechneten Wert nach RefreshRowCell überschreibt.
Dim oFormulaExpression = ObjectEx.NotNull(oColumnData.Item("FORMULA_EXPRESSION"), String.Empty)
If oFormulaExpression <> String.Empty Then
_Logger.Debug("Skipping ColumnEdit assignment for formula column [{0}] using DisplayFormat only.", oCol.FieldName)
Continue For
End If
Dim oColumnType As String = oColumnData.Item("TYPE_COLUMN") Dim oColumnType As String = oColumnData.Item("TYPE_COLUMN")
Select Case oColumnType Select Case oColumnType
@@ -337,6 +346,15 @@ Namespace ControlCreator
Next Next
End Sub End Sub
Public Sub ConfigureViewEvents(pColumnTable As DataTable, pGridView As GridView, pControl As Windows.Forms.Control, pControlId As Integer) Public Sub ConfigureViewEvents(pColumnTable As DataTable, pGridView As GridView, pControl As Windows.Forms.Control, pControlId As Integer)
' Formel-Spalten-Namen einmalig cachen für View_ShowingEditor
_FormulaColumnNames.Clear()
For Each r As DataRow In pColumnTable.Rows
Dim oExpr = ObjectEx.NotNull(r.Item("FORMULA_EXPRESSION"), String.Empty).ToString()
If oExpr <> String.Empty Then
_FormulaColumnNames.Add(r.Item("SPALTENNAME").ToString())
End If
Next
AddHandler pGridView.InitNewRow, Sub(sender As Object, e As InitNewRowEventArgs) AddHandler pGridView.InitNewRow, Sub(sender As Object, e As InitNewRowEventArgs)
Try Try
_Logger.Debug("Initialzing new row") _Logger.Debug("Initialzing new row")
@@ -394,30 +412,233 @@ Namespace ControlCreator
End Sub End Sub
AddHandler pGridView.PopupMenuShowing, AddressOf View_PopupMenuShowing AddHandler pGridView.PopupMenuShowing, AddressOf View_PopupMenuShowing
AddHandler pGridView.InvalidRowException, AddressOf View_InvalidRowException AddHandler pGridView.InvalidRowException, AddressOf View_InvalidRowException
AddHandler pGridView.ValidatingEditor, AddressOf View_ValidatingEditor AddHandler pGridView.ValidatingEditor, AddressOf View_ValidatingEditor
' AddHandler pGridView.CustomColumnDisplayText, AddressOf View_CustomColumnDisplayText AddHandler pGridView.ShownEditor,
Sub(sender As Object, e As EventArgs)
Dim view As GridView = TryCast(sender, GridView)
If view.IsNewItemRow(view.FocusedRowHandle) Then
_Logger.Debug("Attaching Modified Handler.")
AddHandler view.ActiveEditor.Modified, Sub()
_Logger.Debug("Row was modified.")
newRowModified = True
End Sub
End If
' *** KRITISCH: LIVE-REFRESH bei JEDER Eingabe (auch NewItemRow!) ***
If view.FocusedColumn IsNot Nothing AndAlso view.ActiveEditor IsNot Nothing Then
Dim oFocusedColumnName As String = view.FocusedColumn.FieldName
' Prüfen ob diese Spalte von Formel-Spalten referenziert wird
Dim oFormulaColumnsToRefresh As New List(Of String)
For Each oColumnData As DataRow In pColumnTable.Rows
Dim oExpr = ObjectEx.NotNull(oColumnData.Item("FORMULA_EXPRESSION"), String.Empty).ToString()
If oExpr = String.Empty Then Continue For
Dim referencedColumns = GetReferencedColumnNames(oExpr)
If referencedColumns.Any(Function(col) String.Equals(col, oFocusedColumnName, StringComparison.OrdinalIgnoreCase)) Then
oFormulaColumnsToRefresh.Add(oColumnData.Item("SPALTENNAME").ToString())
End If
Next
If oFormulaColumnsToRefresh.Count > 0 Then
_Logger.Debug("[FormulaRefresh] Attaching EditValueChanged handler for LIVE formula updates on column [{0}].", oFocusedColumnName)
' Handler für LIVE Aktualisierung während JEDER Eingabe
AddHandler view.ActiveEditor.EditValueChanged,
Sub(editorSender As Object, editorArgs As EventArgs)
Try
Dim oRowHandle As Integer = view.FocusedRowHandle
If Not view.IsValidRowHandle(oRowHandle) Then Return
Dim oEditor As DevExpress.XtraEditors.BaseEdit = TryCast(editorSender, DevExpress.XtraEditors.BaseEdit)
If oEditor Is Nothing Then Return
Dim isNewItemRow As Boolean = view.IsNewItemRow(oRowHandle)
Try
Dim oValue As Object = oEditor.EditValue
If TypeOf oEditor Is DevExpress.XtraEditors.TextEdit Then
Dim oTextEdit As DevExpress.XtraEditors.TextEdit = DirectCast(oEditor, DevExpress.XtraEditors.TextEdit)
If oTextEdit.Properties.MaskSettings IsNot Nothing Then
oValue = oEditor.EditValue
End If
End If
If isNewItemRow Then
_Logger.Debug("[FormulaRefresh] EditValueChanged (NewItemRow) setting value for [{0}] = [{1}].", oFocusedColumnName, oValue)
_isRefreshingFormula = True
Try
' Wert setzen
view.SetRowCellValue(oRowHandle, oFocusedColumnName, If(oValue Is Nothing, DBNull.Value, oValue))
' *** KRITISCH: DoEvents() damit SetRowCellValue processed wird ***
view.UpdateCurrentRow()
' Formel-Spalten SOFORT refreshen
For Each oFormulaColumnName As String In oFormulaColumnsToRefresh
Dim oGridColumn As GridColumn = view.Columns.ColumnByFieldName(oFormulaColumnName)
If oGridColumn IsNot Nothing Then
view.RefreshRowCell(oRowHandle, oGridColumn)
_Logger.Debug("[FormulaRefresh] (NewItemRow) Refreshed [{0}], current value: [{1}]",
oFormulaColumnName, view.GetRowCellValue(oRowHandle, oGridColumn))
End If
Next
Finally
_isRefreshingFormula = False
End Try
Else
' Bestehende Row
Dim oDataRow As DataRow = view.GetDataRow(oRowHandle)
If oDataRow IsNot Nothing Then
_Logger.Debug("[FormulaRefresh] EditValueChanged setting value for [{0}] in DataTable.", oFocusedColumnName)
oDataRow.Item(oFocusedColumnName) = If(oValue Is Nothing, DBNull.Value, oValue)
For Each oFormulaColumnName As String In oFormulaColumnsToRefresh
Dim oGridColumn As GridColumn = view.Columns.ColumnByFieldName(oFormulaColumnName)
If oGridColumn IsNot Nothing Then
view.RefreshRowCell(oRowHandle, oGridColumn)
Dim currentValue = view.GetRowCellValue(oRowHandle, oGridColumn)
_Logger.Debug("[FormulaRefresh] Current value for [{0}]: [{1}]", oFormulaColumnName, currentValue)
End If
Next
End If
End If
Catch parseEx As Exception
_Logger.Debug("[FormulaRefresh] Parse error during EditValueChanged: {0}", parseEx.Message)
End Try
Catch ex As Exception
_Logger.Error(ex)
End Try
End Sub
End If
End If
End Sub
' These handlers are all used for the custom DefaultValue functionality, additionally some code in the 'InitNewRow' event.
' https://supportcenter.devexpress.com/ticket/details/t1035580/how-to-default-a-value-in-a-column-when-add-new-row-in-data-grid
AddHandler pGridView.ShowingEditor, AddressOf View_ShowingEditor
AddHandler pGridView.ShownEditor, AddressOf View_ShownEditor
AddHandler pGridView.ValidateRow, AddressOf View_ValidateRow AddHandler pGridView.ValidateRow, AddressOf View_ValidateRow
AddHandler pControl.LostFocus, AddressOf Control_LostFocus AddHandler pControl.LostFocus, AddressOf Control_LostFocus
AddHandler pGridView.ShowingEditor,
Sub(sender As Object, e As CancelEventArgs)
Try
Dim oView As GridView = TryCast(sender, GridView)
If oView Is Nothing Then Return
_Logger.Debug("Showing editor.")
' Formel-Spalten dürfen keinen Editor öffnen
If oView.FocusedColumn IsNot Nothing Then
Dim oFieldName As String = oView.FocusedColumn.FieldName
If _FormulaColumnNames.Contains(oFieldName) Then
_Logger.Debug("Cancelling editor column [{0}] is a formula column.", oFieldName)
e.Cancel = True
Return
End If
End If
If oView.IsNewItemRow(oView.FocusedRowHandle) AndAlso Not newRowModified Then
_Logger.Debug("Adding new row.")
oView.AddNewRow()
End If
Catch ex As Exception
_Logger.Error(ex)
End Try
End Sub
AddHandler pGridView.FocusedColumnChanged,
Sub(sender As Object, e As FocusedColumnChangedEventArgs)
Try
Dim oView As GridView = TryCast(sender, GridView)
If oView Is Nothing Then Return
Dim oRowHandle As Integer = oView.FocusedRowHandle
If oView.IsNewItemRow(oRowHandle) Then Return
If Not oView.IsValidRowHandle(oRowHandle) Then Return
If oView.FocusedColumn IsNot Nothing AndAlso
_FormulaColumnNames.Contains(oView.FocusedColumn.FieldName) Then
_Logger.Debug("[FormulaRefresh] FocusedColumnChanged closing editor on formula column [{0}].", oView.FocusedColumn.FieldName)
oView.CloseEditor()
End If
Catch ex As Exception
_Logger.Error(ex)
End Try
End Sub
AddHandler pGridView.CellValueChanged, AddHandler pGridView.CellValueChanged,
Sub(sender As Object, e As CellValueChangedEventArgs) Sub(sender As Object, e As CellValueChangedEventArgs)
' *** HandleInheritedColumnValue MUSS zuerst aufgerufen werden ***
Try Try
HandleInheritedColumnValue(TryCast(sender, GridView), pColumnTable, e) HandleInheritedColumnValue(TryCast(sender, GridView), pColumnTable, e)
Catch ex As Exception Catch ex As Exception
_Logger.Error(ex) _Logger.Error(ex)
End Try End Try
' *** Formel-Refresh via CellValueChanged ist FALLBACK ***
' (EditValueChanged macht das normalerweise schon LIVE)
Try
Dim oView As GridView = TryCast(sender, GridView)
If oView Is Nothing OrElse e.Column Is Nothing Then Return
' Prüfen ob überhaupt eine Formel-Spalte referenziert wird
Dim oFormulaColumnsToRefresh As New List(Of String)
For Each oColumnData As DataRow In pColumnTable.Rows
Dim oExpr = ObjectEx.NotNull(oColumnData.Item("FORMULA_EXPRESSION"), String.Empty).ToString()
If oExpr = String.Empty Then Continue For
Dim referencedColumns = GetReferencedColumnNames(oExpr)
If referencedColumns.Any(Function(col) String.Equals(col, e.Column.FieldName, StringComparison.OrdinalIgnoreCase)) Then
oFormulaColumnsToRefresh.Add(oColumnData.Item("SPALTENNAME").ToString())
End If
Next
If oFormulaColumnsToRefresh.Count = 0 Then
Return
End If
' *** FALLBACK: Nur wenn EditValueChanged NICHT gefeuert hat ***
' (z.B. bei programmatischer SetRowCellValue oder Paste)
Dim oRowHandle As Integer = e.RowHandle
_Logger.Debug("[FormulaRefresh] CellValueChanged FALLBACK refreshing for row [{0}] after column [{1}] changed.", oRowHandle, e.Column.FieldName)
oView.GridControl.BeginInvoke(New Action(
Sub()
Try
If Not oView.IsValidRowHandle(oRowHandle) Then Return
For Each oFormulaColumnName As String In oFormulaColumnsToRefresh
Dim oGridColumn As GridColumn = oView.Columns.ColumnByFieldName(oFormulaColumnName)
If oGridColumn Is Nothing Then Continue For
oView.RefreshRowCell(oRowHandle, oGridColumn)
_Logger.Debug("[FormulaRefresh] FALLBACK DisplayText for [{0}]: [{1}]",
oFormulaColumnName, oView.GetRowCellDisplayText(oRowHandle, oGridColumn))
Next
Catch ex As Exception
_Logger.Error(ex)
End Try
End Sub))
Catch ex As Exception
_Logger.Error(ex)
End Try
End Sub End Sub
End Sub End Sub
Private Sub HandleInheritedColumnValue(pView As GridView, pColumnDefinition As DataTable, pArgs As CellValueChangedEventArgs) Private Sub HandleInheritedColumnValue(pView As GridView, pColumnDefinition As DataTable, pArgs As CellValueChangedEventArgs)
If pView Is Nothing OrElse pArgs Is Nothing OrElse pArgs.Column Is Nothing Then If pView Is Nothing OrElse pArgs Is Nothing OrElse pArgs.Column Is Nothing Then
Return Return
End If End If
' *** NEU: Bei Formel-Refresh überspringen ***
If _isRefreshingFormula Then
_Logger.Debug("Skipping HandleInheritedColumnValue during formula refresh.")
Return
End If
If isApplyingInheritedValue OrElse pArgs.RowHandle = DevExpress.XtraGrid.GridControl.InvalidRowHandle Then If isApplyingInheritedValue OrElse pArgs.RowHandle = DevExpress.XtraGrid.GridControl.InvalidRowHandle Then
Return Return
@@ -642,28 +863,12 @@ Namespace ControlCreator
End If End If
End Sub End Sub
Private Sub View_ShowingEditor(sender As Object, e As CancelEventArgs)
Dim view As GridView = TryCast(sender, GridView)
_Logger.Debug("Showing editor.")
If view.IsNewItemRow(view.FocusedRowHandle) AndAlso Not newRowModified Then
_Logger.Debug("Adding new row.")
view.AddNewRow()
End If
End Sub
Private Sub View_ShownEditor(sender As Object, e As EventArgs)
Dim view As GridView = TryCast(sender, GridView)
If view.IsNewItemRow(view.FocusedRowHandle) Then
_Logger.Debug("Attaching Modified Handler.")
AddHandler view.ActiveEditor.Modified, Sub()
_Logger.Debug("Row was modified.")
newRowModified = True
End Sub
End If
End Sub
Private Sub View_ValidateRow(sender As Object, e As ValidateRowEventArgs) Private Sub View_ValidateRow(sender As Object, e As ValidateRowEventArgs)
Dim view As GridView = TryCast(sender, GridView) Dim view As GridView = TryCast(sender, GridView)
' RowHandle für RowUpdated merken, bevor er sich nach dem Commit ändert
If view.IsNewItemRow(e.RowHandle) AndAlso Not newRowModified Then If view.IsNewItemRow(e.RowHandle) AndAlso Not newRowModified Then
_Logger.Debug("Deleting unused row") _Logger.Debug("Deleting unused row")
view.DeleteRow(e.RowHandle) view.DeleteRow(e.RowHandle)

View File

@@ -98,8 +98,13 @@ Public Class clsPatterns
lookup.Properties.SelectedValues = New List(Of String) From {newValue.ToString()} lookup.Properties.SelectedValues = New List(Of String) From {newValue.ToString()}
End If End If
Case GetType(Windows.Forms.ComboBox) ' ========== FIX START: Beide ComboBox-Typen unterstützen ==========
DirectCast(ctrl, ComboBox).Text = newValue?.ToString() Case GetType(System.Windows.Forms.ComboBox)
DirectCast(ctrl, System.Windows.Forms.ComboBox).Text = newValue?.ToString()
Case GetType(DevExpress.XtraEditors.ComboBoxEdit)
DirectCast(ctrl, DevExpress.XtraEditors.ComboBoxEdit).Text = newValue?.ToString()
' ========== FIX END ==========
Case GetType(CheckBox) Case GetType(CheckBox)
If TypeOf newValue Is Boolean Then If TypeOf newValue Is Boolean Then

View File

@@ -2,8 +2,21 @@
Public Class frmError Public Class frmError
Public ValidatorError As String = "" Public ValidatorError As String = ""
Private _isClosing As Boolean = False
Private Sub OK_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OK_Button.Click Private Sub OK_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OK_Button.Click
Me.Close() ' ========== FIX 1: Event-Handler SOFORT deregistrieren ==========
RemoveHandler OK_Button.Click, AddressOf OK_Button_Click
' ========== DIAGNOSE: StackTrace ausgeben ==========
Dim st As New StackTrace(True)
LOGGER.Debug($"[frmError] OK_Button_Click aufgerufen von:")
For Each frame As StackFrame In st.GetFrames()
LOGGER.Debug($" {frame.GetMethod()?.DeclaringType?.Name}.{frame.GetMethod()?.Name} (Zeile {frame.GetFileLineNumber()})")
Next
' ========== ENDE DIAGNOSE ==========
CloseDialog()
End Sub End Sub
Private Sub frmError_Load(sender As Object, e As System.EventArgs) Handles Me.Load Private Sub frmError_Load(sender As Object, e As System.EventArgs) Handles Me.Load
@@ -27,7 +40,45 @@ Public Class frmError
End If End If
End Sub End Sub
Private Sub frmError_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown Private Sub CloseDialog()
Me.Label1.Focus() ' ========== FIX 2: Guard mit Dispose-Check ==========
If _isClosing OrElse Me.IsDisposed Then
LOGGER.Debug($"[frmError] CloseDialog blockiert (isClosing={_isClosing}, IsDisposed={Me.IsDisposed})")
Exit Sub
End If
_isClosing = True
LOGGER.Debug($"[frmError] CloseDialog: Flag gesetzt, starte verzögerten Close")
' ========== FIX 3: VERZÖGERTER Close via BeginInvoke ==========
' KRITISCH: Close wird NACH Abschluss des aktuellen Event-Handlers ausgeführt
Me.BeginInvoke(New Action(Sub()
If Not Me.IsDisposed Then
Me.DialogResult = DialogResult.OK
Me.Close()
LOGGER.Debug($"[frmError] Dialog geschlossen via BeginInvoke")
End If
End Sub))
' ========== ENDE FIX 3 ==========
End Sub End Sub
Private Sub frmError_Shown(sender As Object, e As EventArgs) Handles Me.Shown
Me.Label1.Focus()
LOGGER.Debug($"[frmError] Dialog angezeigt - Enabled: {Me.Enabled}")
End Sub
Private Sub frmError_Activated(sender As Object, e As EventArgs) Handles Me.Activated
LOGGER.Debug($"[frmError] Dialog aktiviert")
End Sub
' ========== FIX 4: FormClosing-Handler hinzufügen ==========
Private Sub frmError_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
If _isClosing Then
LOGGER.Debug($"[frmError] FormClosing: Close bereits aktiv, erlauben")
Return
End If
' Falls Close von außen (z.B. [X]-Button) ausgelöst wurde
_isClosing = True
LOGGER.Debug($"[frmError] FormClosing: Flag gesetzt via FormClosing")
End Sub
' ========== ENDE FIX 4 ==========
End Class End Class

View File

@@ -136,6 +136,10 @@ Public Class frmValidator
Private _isUpdatingLookup As Boolean = False Private _isUpdatingLookup As Boolean = False
Private _suppressLookupEvents As Boolean = False Private _suppressLookupEvents As Boolean = False
Private _overlayActive As Boolean = False Private _overlayActive As Boolean = False
Private _isShowingErrorDialog As Boolean = False ' ← NEU: Klassenvariable oben hinzufügen
Private _overlayHandle As Object = Nothing ' ← NEU: Klassenvariable
Private Class Translation_Strings Private Class Translation_Strings
Inherits My.Resources.frmValidator_Strings Inherits My.Resources.frmValidator_Strings
End Class End Class
@@ -2084,9 +2088,17 @@ Public Class frmValidator
If oView.FocusedRowHandle < 0 Then Exit Sub If oView.FocusedRowHandle < 0 Then Exit Sub
' Nicht löschen wenn eine Zelle gerade bearbeitet wird ' Nicht löschen wenn eine Zelle gerade bearbeitet wird
If oView.ActiveEditor IsNot Nothing Then Exit Sub If oView.ActiveEditor IsNot Nothing Then Exit Sub
Dim oGrid As GridControl = oView.GridControl Dim oGrid As GridControl = oView.GridControl
Dim oMeta As ClassControlCreator.ControlMetadata = TryCast(oGrid.Tag, ClassControlCreator.ControlMetadata) Dim oMeta As ClassControlCreator.ControlMetadata = TryCast(oGrid.Tag, ClassControlCreator.ControlMetadata)
If oMeta IsNot Nothing AndAlso oMeta.ReadOnly Then
MyValidationLogger.Debug($"[GridView_KeyDown] Grid [{oMeta.Name}] ist ReadOnly → Löschen blockiert")
e.Handled = True
e.SuppressKeyPress = True
Exit Sub
End If
If oMeta IsNot Nothing Then If oMeta IsNot Nothing Then
oMeta.IsDirty = True oMeta.IsDirty = True
MyValidationLogger.Debug($"[GridView_KeyDown] Grid [{oMeta.Name}] marked as dirty") MyValidationLogger.Debug($"[GridView_KeyDown] Grid [{oMeta.Name}] marked as dirty")
@@ -5188,20 +5200,34 @@ Public Class frmValidator
End If End If
btnSave.Enabled = False btnSave.Enabled = False
' ========== ENDE FIX 1 ========== ' ========== ENDE FIX 1 ==========
Dim oHandle = SplashScreenManager.ShowOverlayForm(Me)
' ========== FIX 2: Overlay-Handle global speichern ==========
_overlayHandle = SplashScreenManager.ShowOverlayForm(Me)
_overlayActive = True
' ========== ENDE FIX 2 ==========
Try Try
If ForceGridValidation() = True Then If ForceGridValidation() = True Then
Finish_WFStep() Finish_WFStep()
End If End If
Finally Finally
' ========== FIX 2: Nur Enable wenn Form NICHT schließt ========== ' ========== FIX 3: Overlay IMMER schließen ==========
_overlayActive = False
Try
SplashScreenManager.CloseOverlayForm(_overlayHandle)
Catch ex As Exception
MyValidationLogger.Warn($"⚠️ [btnSave_Click] Overlay-Close failed: {ex.Message}")
End Try
_overlayHandle = Nothing
' ========== ENDE FIX 3 ==========
' ========== FIX 4: Button nur re-enablen wenn Form nicht schließt ==========
If Not _FormClosing AndAlso Not Me.IsDisposed Then If Not _FormClosing AndAlso Not Me.IsDisposed Then
btnSave.Enabled = True btnSave.Enabled = True
Else Else
MyValidationLogger.Debug("btnSave_Click: Form closing, Button bleibt disabled") MyValidationLogger.Debug("btnSave_Click: Form closing, Button bleibt disabled")
End If End If
SplashScreenManager.CloseOverlayForm(oHandle) ' ========== ENDE FIX 4 ==========
' ========== ENDE FIX 2 ==========
End Try End Try
End Sub End Sub
@@ -5710,12 +5736,20 @@ Public Class frmValidator
End Try End Try
Else Else
errormessage = oErrMsgMissingInput errormessage = oErrMsgMissingInput
frmError.ShowDialog() MyValidationLogger.Warn($"⚠️ [Finish_WFStep] Validierung fehlgeschlagen → OpenfrmError")
OpenfrmError(oErrMsgMissingInput) ' ← Statt: frmError.ShowDialog()
oErrorOcurred = True oErrorOcurred = True
' ========== FIX: Overlay schließen NACH Dialog ==========
If overlayStartedHere Then If overlayStartedHere Then
_overlayActive = False _overlayActive = False
SplashScreenManager.CloseOverlayForm(oHandle) Try
SplashScreenManager.CloseOverlayForm(_overlayHandle)
Catch ex As Exception
MyValidationLogger.Warn($"⚠️ [Finish_WFStep] Overlay-Close failed: {ex.Message}")
End Try
_overlayHandle = Nothing
End If End If
' ========== ENDE FIX ==========
Exit Sub Exit Sub
End If End If
Else Else
@@ -5777,7 +5811,17 @@ Public Class frmValidator
End If End If
Focus_FirstControl() Focus_FirstControl()
End If End If
' ========== FIX: Overlay schließen am Ende ==========
If overlayStartedHere Then
_overlayActive = False
Try
SplashScreenManager.CloseOverlayForm(_overlayHandle)
Catch ex As Exception
MyValidationLogger.Warn($"⚠️ [Finish_WFStep] Overlay-Close failed: {ex.Message}")
End Try
_overlayHandle = Nothing
End If
' ========== ENDE FIX ==========
If LOG_HOTSPOTS Then If LOG_HOTSPOTS Then
MyValidationLogger.Info($"[PERF] Finish_WFStep GESAMT: {(DateTime.Now - perfStart).TotalMilliseconds}ms") MyValidationLogger.Info($"[PERF] Finish_WFStep GESAMT: {(DateTime.Now - perfStart).TotalMilliseconds}ms")
End If End If
@@ -6181,6 +6225,11 @@ Public Class frmValidator
oErrMsgMissingInput &= ":" & vbCrLf & oRegexMessage oErrMsgMissingInput &= ":" & vbCrLf & oRegexMessage
End If End If
oControl.BackColor = Color.Red oControl.BackColor = Color.Red
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
OpenfrmError(oErrMsgMissingInput) OpenfrmError(oErrMsgMissingInput)
Exit For Exit For
End If End If
@@ -6246,6 +6295,11 @@ Public Class frmValidator
oMissing = True oMissing = True
oErrMsgMissingInput = $"Error while indexing Textbox {oControl} - Attribute {oIndexName} as VEKTOR - ERROR: " & idxerr_message oErrMsgMissingInput = $"Error while indexing Textbox {oControl} - Attribute {oIndexName} as VEKTOR - ERROR: " & idxerr_message
MyValidationLogger.Warn(oErrMsgMissingInput) MyValidationLogger.Warn(oErrMsgMissingInput)
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
OpenfrmError(oErrMsgMissingInput) OpenfrmError(oErrMsgMissingInput)
Exit For Exit For
End If End If
@@ -6259,6 +6313,11 @@ Public Class frmValidator
oMissing = True oMissing = True
oErrMsgMissingInput = $"Error while indexing Textbox {oControl} - Attribute {oIndexName} - ERROR: " & idxerr_message oErrMsgMissingInput = $"Error while indexing Textbox {oControl} - Attribute {oIndexName} - ERROR: " & idxerr_message
MyValidationLogger.Warn(oErrMsgMissingInput) MyValidationLogger.Warn(oErrMsgMissingInput)
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
OpenfrmError(oErrMsgMissingInput) OpenfrmError(oErrMsgMissingInput)
Exit For Exit For
End If End If
@@ -6282,6 +6341,11 @@ Public Class frmValidator
Dim st As New StackTrace(True) Dim st As New StackTrace(True)
st = New StackTrace(ex, True) st = New StackTrace(ex, True)
MyValidationLogger.Warn("⚠️ Unexpected error in Check_UpdateIndexe TextBox :" & ex.Message, True) MyValidationLogger.Warn("⚠️ Unexpected error in Check_UpdateIndexe TextBox :" & ex.Message, True)
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
OpenfrmError(oErrMsgMissingInput) OpenfrmError(oErrMsgMissingInput)
' Nach Fehler: Dirty-Flag zurücksetzen ' Nach Fehler: Dirty-Flag zurücksetzen
@@ -6298,6 +6362,11 @@ Public Class frmValidator
oMissing = True oMissing = True
oErrMsgMissingInput = "Please Choose an entry out of ComboBox '" & cmb.Name & "'" oErrMsgMissingInput = "Please Choose an entry out of ComboBox '" & cmb.Name & "'"
MyValidationLogger.Warn(oErrMsgMissingInput) MyValidationLogger.Warn(oErrMsgMissingInput)
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
OpenfrmError(oErrMsgMissingInput) OpenfrmError(oErrMsgMissingInput)
Exit For Exit For
Else Else
@@ -6349,6 +6418,11 @@ Public Class frmValidator
oMissing = True oMissing = True
oErrMsgMissingInput = "Error while indexing Combobox as VEKTOR - ERROR: " & idxerr_message oErrMsgMissingInput = "Error while indexing Combobox as VEKTOR - ERROR: " & idxerr_message
MyValidationLogger.Warn(oErrMsgMissingInput) MyValidationLogger.Warn(oErrMsgMissingInput)
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
OpenfrmError(oErrMsgMissingInput) OpenfrmError(oErrMsgMissingInput)
Exit For Exit For
End If End If
@@ -6362,6 +6436,11 @@ Public Class frmValidator
oMissing = True oMissing = True
oErrMsgMissingInput = "Error while indexing Combobox - ERROR: " & idxerr_message oErrMsgMissingInput = "Error while indexing Combobox - ERROR: " & idxerr_message
MyValidationLogger.Warn(oErrMsgMissingInput) MyValidationLogger.Warn(oErrMsgMissingInput)
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
OpenfrmError(oErrMsgMissingInput) OpenfrmError(oErrMsgMissingInput)
Exit For Exit For
End If End If
@@ -6371,6 +6450,11 @@ Public Class frmValidator
oMissing = True oMissing = True
oErrMsgMissingInput = "Error indexing combobox idb" oErrMsgMissingInput = "Error indexing combobox idb"
MyValidationLogger.Warn(oErrMsgMissingInput) MyValidationLogger.Warn(oErrMsgMissingInput)
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
OpenfrmError(oErrMsgMissingInput) OpenfrmError(oErrMsgMissingInput)
Exit For Exit For
End If End If
@@ -6405,6 +6489,11 @@ Public Class frmValidator
oMissing = True oMissing = True
oErrMsgMissingInput = "Please Choose DateValue for field'" & dtp.Name & "'" oErrMsgMissingInput = "Please Choose DateValue for field'" & dtp.Name & "'"
MyValidationLogger.Warn(oErrMsgMissingInput) MyValidationLogger.Warn(oErrMsgMissingInput)
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
OpenfrmError(oErrMsgMissingInput) OpenfrmError(oErrMsgMissingInput)
Exit For Exit For
ElseIf dtp.Value.ToString <> "01.01.0001 00:00:00" Then ElseIf dtp.Value.ToString <> "01.01.0001 00:00:00" Then
@@ -6425,6 +6514,11 @@ Public Class frmValidator
oMissing = True oMissing = True
oErrMsgMissingInput = "Error while indexing DatePicker as VEKTOR - ERROR: " & idxerr_message oErrMsgMissingInput = "Error while indexing DatePicker as VEKTOR - ERROR: " & idxerr_message
MyValidationLogger.Warn(oErrMsgMissingInput) MyValidationLogger.Warn(oErrMsgMissingInput)
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
OpenfrmError(oErrMsgMissingInput) OpenfrmError(oErrMsgMissingInput)
Exit For Exit For
End If End If
@@ -6437,6 +6531,11 @@ Public Class frmValidator
oMissing = True oMissing = True
oErrMsgMissingInput = "Error while indexing DatePicker- ERROR: " & idxerr_message oErrMsgMissingInput = "Error while indexing DatePicker- ERROR: " & idxerr_message
MyValidationLogger.Warn(oErrMsgMissingInput) MyValidationLogger.Warn(oErrMsgMissingInput)
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
OpenfrmError(oErrMsgMissingInput) OpenfrmError(oErrMsgMissingInput)
Exit For Exit For
End If End If
@@ -6445,6 +6544,16 @@ Public Class frmValidator
oMissing = True oMissing = True
oErrMsgMissingInput = "Error indexing datepicker idb" oErrMsgMissingInput = "Error indexing datepicker idb"
MyValidationLogger.Warn(oErrMsgMissingInput) MyValidationLogger.Warn(oErrMsgMissingInput)
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
OpenfrmError(oErrMsgMissingInput) OpenfrmError(oErrMsgMissingInput)
Exit For Exit For
End If End If
@@ -6477,6 +6586,11 @@ Public Class frmValidator
oMissing = True oMissing = True
oErrMsgMissingInput = "Please set Checkbox value for field '" & chk.Name & "'" oErrMsgMissingInput = "Please set Checkbox value for field '" & chk.Name & "'"
MyValidationLogger.Warn(oErrMsgMissingInput) MyValidationLogger.Warn(oErrMsgMissingInput)
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
OpenfrmError(oErrMsgMissingInput) OpenfrmError(oErrMsgMissingInput)
Exit For Exit For
End If End If
@@ -6525,6 +6639,11 @@ Public Class frmValidator
oMissing = True oMissing = True
oErrMsgMissingInput = "Error while indexing Checkbox as VEKTOR - ERROR: " & idxerr_message oErrMsgMissingInput = "Error while indexing Checkbox as VEKTOR - ERROR: " & idxerr_message
MyValidationLogger.Warn(oErrMsgMissingInput) MyValidationLogger.Warn(oErrMsgMissingInput)
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
OpenfrmError(oErrMsgMissingInput) OpenfrmError(oErrMsgMissingInput)
Exit For Exit For
End If End If
@@ -6534,12 +6653,22 @@ Public Class frmValidator
oMissing = True oMissing = True
oErrMsgMissingInput = "Error while indexing Checkbox - ERROR: " & idxerr_message oErrMsgMissingInput = "Error while indexing Checkbox - ERROR: " & idxerr_message
MyValidationLogger.Warn(oErrMsgMissingInput) MyValidationLogger.Warn(oErrMsgMissingInput)
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
OpenfrmError(oErrMsgMissingInput) OpenfrmError(oErrMsgMissingInput)
Exit For Exit For
End If End If
Else Else
If IDBData.SetVariableValue(oIndexName, chk.Checked.ToString) Then If IDBData.SetVariableValue(oIndexName, chk.Checked.ToString) Then
oErrMsgMissingInput = "error indexing checkbox idb" oErrMsgMissingInput = "error indexing checkbox idb"
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
OpenfrmError(oErrMsgMissingInput) OpenfrmError(oErrMsgMissingInput)
Exit For Exit For
End If End If
@@ -6572,6 +6701,11 @@ Public Class frmValidator
oMissing = True oMissing = True
oErrMsgMissingInput = "Fehlende Eingabe in Vektorfeld '" & dgv.Name & "'" oErrMsgMissingInput = "Fehlende Eingabe in Vektorfeld '" & dgv.Name & "'"
MyValidationLogger.Warn(oErrMsgMissingInput) MyValidationLogger.Warn(oErrMsgMissingInput)
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
OpenfrmError(oErrMsgMissingInput) OpenfrmError(oErrMsgMissingInput)
Exit For Exit For
ElseIf Zeilen > 0 Then ElseIf Zeilen > 0 Then
@@ -6608,6 +6742,11 @@ Public Class frmValidator
oMissing = True oMissing = True
oErrMsgMissingInput = "Error while indexing Vektorfeld - ERROR: " & idxerr_message oErrMsgMissingInput = "Error while indexing Vektorfeld - ERROR: " & idxerr_message
MyValidationLogger.Warn(oErrMsgMissingInput) MyValidationLogger.Warn(oErrMsgMissingInput)
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
OpenfrmError(oErrMsgMissingInput) OpenfrmError(oErrMsgMissingInput)
Exit For Exit For
End If End If
@@ -6618,6 +6757,11 @@ Public Class frmValidator
oMissing = True oMissing = True
oErrMsgMissingInput = "Error indexing Datagridview idb" oErrMsgMissingInput = "Error indexing Datagridview idb"
MyValidationLogger.Warn(oErrMsgMissingInput) MyValidationLogger.Warn(oErrMsgMissingInput)
' Vor ShowDialog prüfen
If _FormClosing Then
MyValidationLogger.Warn("Form closing - skip error dialog")
Return False
End If
OpenfrmError(oErrMsgMissingInput) OpenfrmError(oErrMsgMissingInput)
Exit For Exit For
End If End If
@@ -6649,7 +6793,8 @@ Public Class frmValidator
Dim oResult = ValidateGridControl(oGrid, oSettings, oGridColumnDefinition, oMissing, oErrMsgMissingInput) Dim oResult = ValidateGridControl(oGrid, oSettings, oGridColumnDefinition, oMissing, oErrMsgMissingInput)
If oResult = False Then If oResult = False Then
Exit For MyValidationLogger.Warn($"⚠️ Validierung fehlgeschlagen für Grid [{oGrid.Name}] → Exit For")
Exit For ' ← SOFORT stoppen, keinen zweiten Dialog!
End If End If
End Select End Select
@@ -6691,9 +6836,30 @@ Public Class frmValidator
End Function End Function
Sub OpenfrmError(pErrormessage As String) Sub OpenfrmError(pErrormessage As String)
Dim ofrm As New frmError ' ========== FIX: Verhindere mehrfache Dialoge ==========
ofrm.ValidatorError = pErrormessage If _isShowingErrorDialog Then
ofrm.ShowDialog() MyValidationLogger.Warn("⚠️ [OpenfrmError] Dialog bereits offen → Exit Sub")
Return
End If
_isShowingErrorDialog = True
' ========== ENDE FIX ==========
' ========== KRITISCH: Overlay NICHT hier schließen! ==========
' Das macht der Aufrufer (Finish_WFStep oder btnSave_Click)!
' ========== ENDE KRITISCH ==========
' 2. Events blockieren
_suppressLookupEvents = True
Try
Using ofrm As New frmError With {.ValidatorError = pErrormessage}
ofrm.ShowDialog(Me)
End Using
Finally
_suppressLookupEvents = False
' ========== FIX: Guard zurücksetzen ==========
_isShowingErrorDialog = False
' ========== ENDE FIX ==========
End Try
End Sub End Sub
Private Class ControlSettings Private Class ControlSettings
Public Name As String Public Name As String
@@ -6712,7 +6878,19 @@ Public Class frmValidator
'Wenn kein Wert ausgewählt wurde und der Index aber gesetzt werden muss 'Wenn kein Wert ausgewählt wurde und der Index aber gesetzt werden muss
If pSettings.IsRequired = True And oRowCount = 0 Then If pSettings.IsRequired = True And oRowCount = 0 Then
pMissing = True pMissing = True
pMissingMessage = "Fehlende Eingabe in Tabelle '" & pGrid.Name & "'" ' ========== NEU: Liste der Required-Spalten sammeln ==========
Dim requiredColumns = pColumnDefinition.AsEnumerable().
Where(Function(row) row.ItemEx("VALIDATION", False) = True).
Select(Function(row) row.ItemEx("SPALTEN_HEADER_LANG", row.ItemEx("SPALTENNAME", "")).ToString()).
Where(Function(colName) Not String.IsNullOrWhiteSpace(colName)).
ToList()
If requiredColumns.Count > 0 Then
pMissingMessage = $"Missing input in table '{pGrid.Name}'. At least on row with following required fields necessary: {String.Join(", ", requiredColumns)}"
Else
pMissingMessage = $"Missing input in table '{pGrid.Name}' - at least one row necessary"
End If
' ========== ENDE NEU ==========
pGrid.BackColor = Color.Red pGrid.BackColor = Color.Red
MyValidationLogger.Warn(pMissingMessage) MyValidationLogger.Warn(pMissingMessage)
@@ -7364,6 +7542,8 @@ Public Class frmValidator
DatabaseFallback.ExecuteNonQueryECM(ins) DatabaseFallback.ExecuteNonQueryECM(ins)
Else Else
SetStatusLabel("Error while saving data!", "Red") SetStatusLabel("Error while saving data!", "Red")
MsgBox("Unexpeceted error while savign data! Please check Your log and try again.", MsgBoxStyle.Critical)
End If End If
' ========== ENDE FIX 2 ========== ' ========== ENDE FIX 2 ==========
Finally Finally